├── .editorconfig ├── .git-blame-ignore-revs ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ └── feature_proposal.yml └── PULL_REQUEST_TEMPLATE.md ├── .runsettings ├── CODE_OF_CONDUCT.md ├── Contributing.md ├── Directory.Build.props ├── Directory.Build.targets ├── License.md ├── README.md ├── ThirdPartyNotices.txt ├── azure-pipelines.yml ├── build ├── Community.Toolkit.Common.props ├── Community.Toolkit.Common.targets ├── Sign-Package.ps1 ├── SignClientSettings.json └── nuget.png ├── dotnet Community Toolkit.sln ├── global.json ├── src ├── CommunityToolkit.Common │ ├── CommunityToolkit.Common.csproj │ ├── Converters.cs │ ├── Deferred │ │ ├── DeferredCancelEventArgs.cs │ │ ├── DeferredEventArgs.cs │ │ └── EventDeferral.cs │ ├── Extensions │ │ ├── ArrayExtensions.cs │ │ ├── EventHandlerExtensions.cs │ │ ├── ISettingsStorageHelperExtensions.cs │ │ ├── StringExtensions.cs │ │ └── TaskExtensions.cs │ ├── Helpers │ │ └── ObjectStorage │ │ │ ├── DirectoryItemType.cs │ │ │ ├── IFileStorageHelper.cs │ │ │ ├── IObjectSerializer.cs │ │ │ ├── ISettingsStorageHelper.cs │ │ │ └── SystemSerializer.cs │ └── IncrementalLoadingCollection │ │ └── IIncrementalSource.cs ├── CommunityToolkit.Diagnostics │ ├── CommunityToolkit.Diagnostics.csproj │ ├── Extensions │ │ ├── TypeExtensions.cs │ │ └── ValueTypeExtensions.cs │ ├── Generated │ │ ├── Guard.Collection.g.cs │ │ ├── Guard.Collection.tt │ │ ├── Guard.Comparable.Numeric.g.cs │ │ ├── Guard.Comparable.Numeric.tt │ │ ├── Guard.md │ │ ├── ThrowHelper.Collection.g.cs │ │ ├── ThrowHelper.Collection.tt │ │ ├── TypeInfo.g.cs │ │ └── TypeInfo.ttinclude │ ├── Guard.Boolean.cs │ ├── Guard.Comparable.Generic.cs │ ├── Guard.Comparable.Numeric.cs │ ├── Guard.IO.cs │ ├── Guard.String.cs │ ├── Guard.Tasks.cs │ ├── Guard.cs │ ├── Internals │ │ ├── Guard.Collection.Generic.ThrowHelper.cs │ │ ├── Guard.Comparable.Generic.ThrowHelper.cs │ │ ├── Guard.Comparable.Numeric.ThrowHelper.cs │ │ ├── Guard.IO.ThrowHelper.cs │ │ ├── Guard.String.ThrowHelper.cs │ │ ├── Guard.Tasks.ThrowHelper.cs │ │ └── Guard.ThrowHelper.cs │ ├── ThrowHelper.Generic.cs │ └── ThrowHelper.cs ├── CommunityToolkit.HighPerformance │ ├── Box{T}.cs │ ├── Buffers │ │ ├── ArrayPoolBufferWriter{T}.cs │ │ ├── Enums │ │ │ └── AllocationMode.cs │ │ ├── Interfaces │ │ │ └── IBuffer{T}.cs │ │ ├── Internals │ │ │ ├── ArrayMemoryManager{TFrom,TTo}.cs │ │ │ ├── Interfaces │ │ │ │ └── IMemoryManager.cs │ │ │ ├── ProxyMemoryManager{TFrom,TTo}.cs │ │ │ ├── RawObjectMemoryManager{T}.cs │ │ │ └── StringMemoryManager{TTo}.cs │ │ ├── MemoryBufferWriter{T}.cs │ │ ├── MemoryOwner{T}.cs │ │ ├── SpanOwner{T}.cs │ │ ├── StringPool.cs │ │ └── Views │ │ │ └── MemoryDebugView{T}.cs │ ├── CommunityToolkit.HighPerformance.csproj │ ├── Enumerables │ │ ├── ReadOnlyRefEnumerable{T}.cs │ │ ├── ReadOnlySpanEnumerable{T}.cs │ │ ├── ReadOnlySpanTokenizer{T}.cs │ │ ├── RefEnumerable{T}.cs │ │ ├── SpanEnumerable{T}.cs │ │ └── SpanTokenizer{T}.cs │ ├── Extensions │ │ ├── ArrayExtensions.1D.cs │ │ ├── ArrayExtensions.2D.cs │ │ ├── ArrayExtensions.3D.cs │ │ ├── ArrayPoolBufferWriterExtensions.cs │ │ ├── ArrayPoolExtensions.cs │ │ ├── BoolExtensions.cs │ │ ├── HashCodeExtensions.cs │ │ ├── IBufferWriterExtensions.cs │ │ ├── IMemoryOwnerExtensions.cs │ │ ├── ListExtensions.cs │ │ ├── MemoryExtensions.cs │ │ ├── NullableExtensions.cs │ │ ├── ReadOnlyMemoryExtensions.cs │ │ ├── ReadOnlySequenceExtensions.cs │ │ ├── ReadOnlySpanExtensions.cs │ │ ├── SpanExtensions.cs │ │ ├── SpinLockExtensions.cs │ │ ├── StreamExtensions.cs │ │ └── StringExtensions.cs │ ├── Helpers │ │ ├── BitHelper.cs │ │ ├── HashCode{T}.cs │ │ ├── Internals │ │ │ ├── BitOperations.cs │ │ │ ├── RefEnumerableHelper.cs │ │ │ ├── RuntimeHelpers.cs │ │ │ ├── SpanHelper.Count.cs │ │ │ └── SpanHelper.Hash.cs │ │ ├── ObjectMarshal.cs │ │ ├── ParallelHelper.For.IAction.cs │ │ ├── ParallelHelper.For.IAction2D.cs │ │ ├── ParallelHelper.ForEach.IInAction.cs │ │ ├── ParallelHelper.ForEach.IInAction2D.cs │ │ ├── ParallelHelper.ForEach.IRefAction.cs │ │ ├── ParallelHelper.ForEach.IRefAction2D.cs │ │ └── ParallelHelper.ThrowExceptions.cs │ ├── Memory │ │ ├── Internals │ │ │ ├── OverflowHelper.cs │ │ │ └── ThrowHelper.cs │ │ ├── Memory2D{T}.cs │ │ ├── ReadOnlyMemory2D{T}.cs │ │ ├── ReadOnlySpan2D{T}.Enumerator.cs │ │ ├── ReadOnlySpan2D{T}.cs │ │ ├── Span2D{T}.Enumerator.cs │ │ ├── Span2D{T}.cs │ │ └── Views │ │ │ └── MemoryDebugView2D{T}.cs │ ├── NullableReadOnlyRef{T}.cs │ ├── NullableRef{T}.cs │ ├── ReadOnlyRef{T}.cs │ ├── Ref{T}.cs │ └── Streams │ │ ├── IBufferWriterStream{TWriter}.Memory.cs │ │ ├── IBufferWriterStream{TWriter}.cs │ │ ├── IMemoryOwnerStream{TSource}.cs │ │ ├── MemoryStream.ThrowExceptions.cs │ │ ├── MemoryStream.Validate.cs │ │ ├── MemoryStream.cs │ │ ├── MemoryStream{TSource}.Memory.cs │ │ ├── MemoryStream{TSource}.cs │ │ ├── ReadOnlySequenceStream.cs │ │ └── Sources │ │ ├── ArrayBufferWriterOwner.cs │ │ ├── ArrayOwner.cs │ │ ├── IBufferWriterOwner.cs │ │ ├── Interfaces │ │ └── ISpanOwner.cs │ │ └── MemoryManagerOwner.cs ├── CommunityToolkit.Mvvm.CodeFixers.Roslyn4001 │ └── CommunityToolkit.Mvvm.CodeFixers.Roslyn4001.csproj ├── CommunityToolkit.Mvvm.CodeFixers.Roslyn4120 │ └── CommunityToolkit.Mvvm.CodeFixers.Roslyn4120.csproj ├── CommunityToolkit.Mvvm.CodeFixers │ ├── AsyncVoidReturningRelayCommandMethodCodeFixer.cs │ ├── ClassUsingAttributeInsteadOfInheritanceCodeFixer.cs │ ├── CommunityToolkit.Mvvm.CodeFixers.projitems │ ├── CommunityToolkit.Mvvm.CodeFixers.props │ ├── CommunityToolkit.Mvvm.CodeFixers.shproj │ ├── FieldReferenceForObservablePropertyFieldCodeFixer.cs │ ├── UsePartialPropertyForObservablePropertyCodeFixer.cs │ └── UsePartialPropertyForSemiAutoPropertyCodeFixer.cs ├── CommunityToolkit.Mvvm.SourceGenerators.Roslyn4001 │ └── CommunityToolkit.Mvvm.SourceGenerators.Roslyn4001.csproj ├── CommunityToolkit.Mvvm.SourceGenerators.Roslyn4031 │ └── CommunityToolkit.Mvvm.SourceGenerators.Roslyn4031.csproj ├── CommunityToolkit.Mvvm.SourceGenerators.Roslyn4120 │ └── CommunityToolkit.Mvvm.SourceGenerators.Roslyn4120.csproj ├── CommunityToolkit.Mvvm.SourceGenerators │ ├── AnalyzerReleases.Shipped.md │ ├── AnalyzerReleases.Unshipped.md │ ├── CommunityToolkit.Mvvm.SourceGenerators.projitems │ ├── CommunityToolkit.Mvvm.SourceGenerators.props │ ├── CommunityToolkit.Mvvm.SourceGenerators.shproj │ ├── ComponentModel │ │ ├── INotifyPropertyChangedGenerator.cs │ │ ├── Models │ │ │ ├── AttributeInfo.cs │ │ │ ├── INotifyPropertyChangedInfo.cs │ │ │ ├── ObservableRecipientInfo.cs │ │ │ ├── PropertyInfo.cs │ │ │ ├── TypedConstantInfo.Factory.cs │ │ │ ├── TypedConstantInfo.cs │ │ │ └── ValidationInfo.cs │ │ ├── ObservableObjectGenerator.cs │ │ ├── ObservablePropertyGenerator.Execute.cs │ │ ├── ObservablePropertyGenerator.cs │ │ ├── ObservableRecipientGenerator.cs │ │ ├── ObservableValidatorValidateAllPropertiesGenerator.Execute.cs │ │ ├── ObservableValidatorValidateAllPropertiesGenerator.cs │ │ ├── TransitiveMembersGenerator.Execute.cs │ │ └── TransitiveMembersGenerator.cs │ ├── Diagnostics │ │ ├── Analyzers │ │ │ ├── AsyncVoidReturningRelayCommandMethodAnalyzer.cs │ │ │ ├── AutoPropertyWithFieldTargetedObservablePropertyAttributeAnalyzer.cs │ │ │ ├── ClassUsingAttributeInsteadOfInheritanceAnalyzer.cs │ │ │ ├── FieldReferenceForObservablePropertyFieldAnalyzer.cs │ │ │ ├── FieldWithOrphanedDependentObservablePropertyAttributesAnalyzer.cs │ │ │ ├── InvalidClassLevelNotifyDataErrorInfoAttributeAnalyzer.cs │ │ │ ├── InvalidClassLevelNotifyPropertyChangedRecipientsAttributeAnalyzer.cs │ │ │ ├── InvalidGeneratedPropertyObservablePropertyAttributeAnalyzer.cs │ │ │ ├── InvalidPartialPropertyLevelObservablePropertyAttributeAnalyzer.cs │ │ │ ├── InvalidPointerTypeObservablePropertyAttributeAnalyzer.cs │ │ │ ├── InvalidPropertyLevelObservablePropertyAttributeAnalyzer.cs │ │ │ ├── InvalidTargetObservablePropertyAttributeAnalyzer.cs │ │ │ ├── PropertyNameCollisionObservablePropertyAttributeAnalyzer.cs │ │ │ ├── RequiresCSharpLanguageVersionPreviewAnalyzer.cs │ │ │ ├── UnsupportedCSharpLanguageVersionAnalyzer.cs │ │ │ ├── UnsupportedRoslynVersionForPartialPropertyAnalyzer.cs │ │ │ ├── UseObservablePropertyOnPartialPropertyAnalyzer.cs │ │ │ ├── UseObservablePropertyOnSemiAutoPropertyAnalyzer.cs │ │ │ ├── WinRTClassUsingNotifyPropertyChangedAttributesAnalyzer.cs │ │ │ ├── WinRTGeneratedBindableCustomPropertyWithBasesMemberAnalyzer.cs │ │ │ ├── WinRTObservablePropertyOnFieldsIsNotAotCompatibleAnalyzer.cs │ │ │ └── WinRTRelayCommandIsNotGeneratedBindableCustomPropertyCompatibleAnalyzer.cs │ │ ├── DiagnosticDescriptors.cs │ │ ├── SuppressionDescriptors.cs │ │ └── Suppressors │ │ │ ├── ObservablePropertyAttributeWithSupportedTargetDiagnosticSuppressor.cs │ │ │ └── RelayCommandAttributeWithFieldOrPropertyTargetDiagnosticSuppressor.cs │ ├── EmbeddedResources │ │ ├── INotifyPropertyChanged.cs │ │ ├── ObservableObject.cs │ │ └── ObservableRecipient.cs │ ├── Extensions │ │ ├── AccessibilityExtensions.cs │ │ ├── AnalyzerConfigOptionsExtensions.cs │ │ ├── AttributeDataExtensions.cs │ │ ├── CompilationExtensions.cs │ │ ├── DiagnosticsExtensions.cs │ │ ├── GeneratorAttributeSyntaxContextWithOptions.cs │ │ ├── INamedTypeSymbolExtensions.cs │ │ ├── ISymbolExtensions.cs │ │ ├── ITypeSymbolExtensions.cs │ │ ├── IncrementalGeneratorInitializationContextExtensions.cs │ │ ├── IncrementalValuesProviderExtensions.cs │ │ ├── MemberDeclarationSyntaxExtensions.cs │ │ ├── MethodDeclarationSyntaxExtensions.cs │ │ ├── SourceProductionContextExtensions.cs │ │ ├── SymbolInfoExtensions.cs │ │ ├── SymbolKindExtensions.cs │ │ ├── SyntaxKindExtensions.cs │ │ ├── SyntaxNodeExtensions.cs │ │ ├── SyntaxTokenExtensions.cs │ │ ├── SyntaxTokenListExtensions.cs │ │ └── TypeDeclarationSyntaxExtensions.cs │ ├── Helpers │ │ ├── EquatableArray{T}.cs │ │ ├── HashCode.cs │ │ ├── ImmutableArrayBuilder{T}.cs │ │ └── ObjectPool{T}.cs │ ├── Input │ │ ├── Models │ │ │ ├── CanExecuteExpressionType.cs │ │ │ └── CommandInfo.cs │ │ ├── RelayCommandGenerator.Execute.cs │ │ └── RelayCommandGenerator.cs │ ├── Messaging │ │ ├── IMessengerRegisterAllGenerator.Execute.cs │ │ ├── IMessengerRegisterAllGenerator.cs │ │ └── Models │ │ │ └── RecipientInfo.cs │ ├── Models │ │ ├── DiagnosticInfo.cs │ │ ├── HierarchyInfo.Syntax.cs │ │ ├── HierarchyInfo.cs │ │ ├── Result.cs │ │ └── TypeInfo.cs │ └── Polyfills │ │ ├── GeneratorAttributeSyntaxContext.cs │ │ └── SyntaxValueProviderExtensions.cs ├── CommunityToolkit.Mvvm │ ├── Collections │ │ ├── IReadOnlyObservableGroup.cs │ │ ├── IReadOnlyObservableGroup{TKey,TElement}.cs │ │ ├── IReadOnlyObservableGroup{TKey}.cs │ │ ├── Internals │ │ │ └── ObservableGroupHelper.cs │ │ ├── ObservableGroupedCollectionExtensions.cs │ │ ├── ObservableGroupedCollection{TKey,TElement}.cs │ │ ├── ObservableGroup{TKey,TElement}.cs │ │ ├── ReadOnlyObservableGroupedCollection{TKey,TElement}.cs │ │ └── ReadOnlyObservableGroup{TKey,TElement}.cs │ ├── CommunityToolkit.Mvvm.FeatureSwitches.targets │ ├── CommunityToolkit.Mvvm.SourceGenerators.targets │ ├── CommunityToolkit.Mvvm.Windows.targets │ ├── CommunityToolkit.Mvvm.WindowsSdk.targets │ ├── CommunityToolkit.Mvvm.csproj │ ├── CommunityToolkit.Mvvm.targets │ ├── ComponentModel │ │ ├── Attributes │ │ │ ├── INotifyPropertyChangedAttribute.cs │ │ │ ├── NotifyCanExecuteChangedForAttribute.cs │ │ │ ├── NotifyDataErrorInfoAttribute.cs │ │ │ ├── NotifyPropertyChangedForAttribute.cs │ │ │ ├── NotifyPropertyChangedRecipientsAttribute.cs │ │ │ ├── ObservableObjectAttribute.cs │ │ │ ├── ObservablePropertyAttribute.cs │ │ │ └── ObservableRecipientAttribute.cs │ │ ├── ObservableObject.cs │ │ ├── ObservableRecipient.cs │ │ ├── ObservableValidator.cs │ │ └── __Internals │ │ │ ├── __ObservableValidatorHelper.cs │ │ │ └── __TaskExtensions.cs │ ├── DependencyInjection │ │ └── Ioc.cs │ ├── Input │ │ ├── AsyncRelayCommand.cs │ │ ├── AsyncRelayCommandOptions.cs │ │ ├── AsyncRelayCommand{T}.cs │ │ ├── Attributes │ │ │ └── RelayCommandAttribute.cs │ │ ├── IAsyncRelayCommandExtensions.cs │ │ ├── Interfaces │ │ │ ├── IAsyncRelayCommand.cs │ │ │ ├── IAsyncRelayCommand{T}.cs │ │ │ ├── IRelayCommand.cs │ │ │ └── IRelayCommand{T}.cs │ │ ├── Internals │ │ │ ├── CancelCommand.cs │ │ │ ├── DisabledCommand.cs │ │ │ └── ICancellationAwareCommand.cs │ │ ├── RelayCommand.cs │ │ └── RelayCommand{T}.cs │ ├── Messaging │ │ ├── IMessenger.cs │ │ ├── IMessengerExtensions.Observables.cs │ │ ├── IMessengerExtensions.cs │ │ ├── IRecipient{TMessage}.cs │ │ ├── Internals │ │ │ ├── ArrayPoolBufferWriter{T}.cs │ │ │ ├── MessageHandlerDispatcher.cs │ │ │ ├── System │ │ │ │ ├── Collections.Generic │ │ │ │ │ ├── Dictionary2.cs │ │ │ │ │ ├── HashHelpers.cs │ │ │ │ │ ├── IDictionary2.cs │ │ │ │ │ ├── IDictionary2{TKey,TValue}.cs │ │ │ │ │ └── IDictionary2{TKey}.cs │ │ │ │ ├── Gen2GcCallback.cs │ │ │ │ └── Runtime.CompilerServices │ │ │ │ │ ├── ConditionalWeakTable2{TKey,TValue}.Proxy.cs │ │ │ │ │ ├── ConditionalWeakTable2{TKey,TValue}.ZeroAlloc.cs │ │ │ │ │ ├── ConditionalWeakTable2{TKey,TValue}.cs │ │ │ │ │ └── ConditionalWeakTableExtensions.cs │ │ │ ├── Type2.cs │ │ │ └── Unit.cs │ │ ├── MessageHandler{TRecipient,TMessage}.cs │ │ ├── Messages │ │ │ ├── AsyncCollectionRequestMessage{T}.cs │ │ │ ├── AsyncRequestMessage{T}.cs │ │ │ ├── CollectionRequestMessage{T}.cs │ │ │ ├── PropertyChangedMessage{T}.cs │ │ │ ├── RequestMessage{T}.cs │ │ │ └── ValueChangedMessage{T}.cs │ │ ├── StrongReferenceMessenger.cs │ │ └── WeakReferenceMessenger.cs │ └── Properties │ │ ├── FeatureSwitches.cs │ │ ├── ILLink.Substitutions.xml │ │ └── Polyfills │ │ └── ArgumentNullException.cs ├── Directory.Build.props └── Directory.Build.targets ├── tests ├── CommunityToolkit.Common.UnitTests │ ├── CommunityToolkit.Common.UnitTests.csproj │ ├── Extensions │ │ ├── Test_ArrayExtensions.cs │ │ ├── Test_EventHandlerExtensions.cs │ │ └── Test_TaskExtensions.cs │ └── Test_Converters.cs ├── CommunityToolkit.Diagnostics.UnitTests │ ├── CommunityToolkit.Diagnostics.UnitTests.csproj │ ├── Extensions │ │ ├── Test_TypeExtensions.cs │ │ └── Test_ValueTypeExtensions.cs │ ├── Test_Guard.Array.cs │ ├── Test_Guard.Comparable.Numeric.cs │ ├── Test_Guard.cs │ └── Test_ThrowHelper.cs ├── CommunityToolkit.HighPerformance.UnitTests │ ├── Buffers │ │ ├── Internals │ │ │ ├── TrackingArrayPool{T}.cs │ │ │ └── UnmanagedSpanOwner.cs │ │ ├── Test_ArrayPoolBufferWriter{T}.cs │ │ ├── Test_MemoryBufferWriter{T}.cs │ │ ├── Test_MemoryOwner{T}.cs │ │ ├── Test_SpanOwner{T}.cs │ │ └── Test_StringPool.cs │ ├── CommunityToolkit.HighPerformance.UnitTests.csproj │ ├── Enumerables │ │ ├── Test_ReadOnlyRefEnumerable{T}.cs │ │ └── Test_RefEnumerable{T}.cs │ ├── Extensions │ │ ├── Test_ArrayExtensions.1D.cs │ │ ├── Test_ArrayExtensions.2D.cs │ │ ├── Test_ArrayExtensions.3D.cs │ │ ├── Test_ArrayPoolExtensions.cs │ │ ├── Test_BoolExtensions.cs │ │ ├── Test_HashCodeExtensions.cs │ │ ├── Test_IBufferWriterExtensions.cs │ │ ├── Test_IMemoryOwnerExtensions.cs │ │ ├── Test_MemoryExtensions.cs │ │ ├── Test_NullableExtensions.cs │ │ ├── Test_ReadOnlyMemoryExtensions.cs │ │ ├── Test_ReadOnlySpanExtensions.Count.cs │ │ ├── Test_ReadOnlySpanExtensions.cs │ │ ├── Test_SpanExtensions.cs │ │ ├── Test_SpinLockExtensions.cs │ │ ├── Test_StreamExtensions.cs │ │ └── Test_StringExtensions.cs │ ├── Helpers │ │ ├── Internals │ │ │ └── Test_RuntimeHelpers.cs │ │ ├── Test_BitHelper.cs │ │ ├── Test_HashCode{T}.cs │ │ ├── Test_ObjectMarshal.cs │ │ ├── Test_ParallelHelper.For.cs │ │ ├── Test_ParallelHelper.For2D.cs │ │ ├── Test_ParallelHelper.ForEach.In.cs │ │ ├── Test_ParallelHelper.ForEach.In2D.cs │ │ ├── Test_ParallelHelper.ForEach.Ref.cs │ │ ├── Test_ParallelHelper.ForEach.Ref2D.cs │ │ └── Test_ParallelHelper.ThrowExceptions.cs │ ├── Memory │ │ ├── Test_Memory2D{T}.cs │ │ ├── Test_ReadOnlyMemory2D{T}.cs │ │ ├── Test_ReadOnlySpan2D{T}.cs │ │ └── Test_Span2D{T}.cs │ ├── Streams │ │ ├── Test_IBufferWriterStream.cs │ │ ├── Test_IMemoryOwnerStream.cs │ │ ├── Test_MemoryStream.ThrowExceptions.cs │ │ ├── Test_MemoryStream.cs │ │ └── Test_ReadOnlySequenceStream.cs │ ├── Test_Box{T}.cs │ ├── Test_NullableReadOnlyRef{T}.cs │ ├── Test_NullableRef{T}.cs │ ├── Test_ReadOnlyRef{T}.cs │ └── Test_Ref{T}.cs ├── CommunityToolkit.Mvvm.DisableINotifyPropertyChanging.UnitTests │ ├── CommunityToolkit.Mvvm.DisableINotifyPropertyChanging.UnitTests.csproj │ └── Test_DisableINotifyPropertyChanging.cs ├── CommunityToolkit.Mvvm.ExternalAssembly.Roslyn4001 │ └── CommunityToolkit.Mvvm.ExternalAssembly.Roslyn4001.csproj ├── CommunityToolkit.Mvvm.ExternalAssembly.Roslyn4031 │ └── CommunityToolkit.Mvvm.ExternalAssembly.Roslyn4031.csproj ├── CommunityToolkit.Mvvm.ExternalAssembly │ ├── CommunityToolkit.Mvvm.ExternalAssembly.projitems │ ├── CommunityToolkit.Mvvm.ExternalAssembly.shproj │ ├── ModelWithObservableObjectAttribute.cs │ ├── ModelWithObservablePropertyAndMethod.cs │ └── SampleModelWithINPCAndObservableProperties.cs ├── CommunityToolkit.Mvvm.Internals.UnitTests │ ├── CommunityToolkit.Mvvm.Internals.UnitTests.csproj │ ├── Test_ConditionalWeakTable2.cs │ ├── Test_Dictionary2.cs │ └── Test_Messenger.cs ├── CommunityToolkit.Mvvm.Roslyn4001.UnitTests │ └── CommunityToolkit.Mvvm.Roslyn4001.UnitTests.csproj ├── CommunityToolkit.Mvvm.Roslyn4031.UnitTests │ └── CommunityToolkit.Mvvm.Roslyn4031.UnitTests.csproj ├── CommunityToolkit.Mvvm.Roslyn4120.UnitTests │ ├── CommunityToolkit.Mvvm.Roslyn4120.UnitTests.csproj │ └── Test_ObservablePropertyAttribute_PartialProperties.cs ├── CommunityToolkit.Mvvm.SourceGenerators.Roslyn4001.UnitTests │ ├── CommunityToolkit.Mvvm.SourceGenerators.Roslyn4001.UnitTests.csproj │ ├── Test_AsyncVoidReturningRelayCommandMethodCodeFixer.cs │ ├── Test_ClassUsingAttributeInsteadOfInheritanceCodeFixer.cs │ ├── Test_FieldReferenceForObservablePropertyFieldCodeFixer.cs │ └── Test_UnsupportedRoslynVersionForPartialPropertyAnalyzer.cs ├── CommunityToolkit.Mvvm.SourceGenerators.Roslyn4031.UnitTests │ └── CommunityToolkit.Mvvm.SourceGenerators.Roslyn4031.UnitTests.csproj ├── CommunityToolkit.Mvvm.SourceGenerators.Roslyn4120.UnitTests │ ├── CommunityToolkit.Mvvm.SourceGenerators.Roslyn4120.UnitTests.csproj │ ├── Test_SourceGeneratorsCodegen.cs │ ├── Test_SourceGeneratorsDiagnostics.cs │ ├── Test_UseObservablePropertyOnSemiAutoPropertyCodeFixer.cs │ └── Test_UsePartialPropertyForObservablePropertyCodeFixer.cs ├── CommunityToolkit.Mvvm.SourceGenerators.UnitTests │ ├── CommunityToolkit.Mvvm.SourceGenerators.UnitTests.projitems │ ├── CommunityToolkit.Mvvm.SourceGenerators.UnitTests.shproj │ ├── Helpers │ │ ├── CSharpAnalyzerWithLanguageVersionTest{TAnalyzer}.cs │ │ └── CSharpCodeFixWithLanguageVersionTest{TAnalyzer,TCodeFix,TVerifier}.cs │ ├── Test_SourceGeneratorsCodegen.cs │ └── Test_SourceGeneratorsDiagnostics.cs └── CommunityToolkit.Mvvm.UnitTests │ ├── Collections │ ├── IntGroup.cs │ ├── Test_ObservableGroup.cs │ ├── Test_ObservableGroupedCollection.cs │ ├── Test_ObservableGroupedCollectionExtensions.cs │ ├── Test_ReadOnlyObservableGroup.cs │ └── Test_ReadOnlyObservableGroupedCollection.cs │ ├── CommunityToolkit.Mvvm.UnitTests.projitems │ ├── CommunityToolkit.Mvvm.UnitTests.shproj │ ├── Helpers │ ├── ExceptionHelper.cs │ └── TaskSchedulerTestHelper.cs │ ├── Test_ArgumentNullException.ComponentModel.cs │ ├── Test_ArgumentNullException.DependencyInjection.cs │ ├── Test_ArgumentNullException.Input.cs │ ├── Test_ArgumentNullException.Messaging.cs │ ├── Test_AsyncRelayCommand.cs │ ├── Test_AsyncRelayCommand{T}.cs │ ├── Test_INotifyPropertyChangedAttribute.cs │ ├── Test_IRecipientGenerator.cs │ ├── Test_Messenger.Observables.cs │ ├── Test_Messenger.Request.cs │ ├── Test_Messenger.cs │ ├── Test_ObservableObject.cs │ ├── Test_ObservableObjectAttribute.cs │ ├── Test_ObservablePropertyAttribute.RootNamespace.cs │ ├── Test_ObservablePropertyAttribute.cs │ ├── Test_ObservableRecipient.cs │ ├── Test_ObservableRecipientAttribute.cs │ ├── Test_ObservableValidator.cs │ ├── Test_RelayCommand.cs │ ├── Test_RelayCommandAttribute.cs │ ├── Test_RelayCommand{T}.cs │ └── Test_SourceGenerators.cs ├── toolkit.snk └── version.json /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Whitespace fixups 2 | eab4b9ed28c27db0c4194478eaa7c6e91664195d 3 | 93cb82a0d01bcf3feb2a79cc1eaf2d47b3c0cdd4 4 | 5 | # Switch to file-scoped namespaces 6 | c176080d37953a2d811c81181192acc8695bbf73 7 | 8 | # Fix leftover file-scoped namespaces 9 | 0693d6c9647c8bea852de8f670e6c32516b18228 -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Question or discussion 4 | url: https://github.com/CommunityToolkit/dotnet/discussions/new 5 | about: I have a question about how to use something in the toolkit 6 | - name: Documentation 7 | url: https://github.com/MicrosoftDocs/CommunityToolkit/issues/new 8 | about: I have a documentation suggestion or question -------------------------------------------------------------------------------- /.runsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 0 4 | 5 | 0 6 | ClassLevel 7 | 8 | 9 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileDirectory) 5 | $(RepositoryDirectory)build\ 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | true 14 | $(RepositoryDirectory)bin\nupkg 15 | true 16 | 17 | 18 | 19 | 20 | false 21 | false 22 | $(NoWarn);CS8002;SA0001 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | true 36 | 37 | true 38 | 39 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <_Parameter1>CommitHash 9 | <_Parameter2>$(SourceRevisionId) 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | # .NET Community Toolkit 2 | 3 | Copyright © .NET Foundation and Contributors 4 | 5 | All rights reserved. 6 | 7 | ## MIT License (MIT) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - main 3 | - dev/* 4 | - rel/* 5 | 6 | pr: 7 | - main 8 | - dev/* 9 | - rel/* 10 | 11 | pool: 12 | vmImage: windows-latest 13 | 14 | variables: 15 | Build.Configuration: Release 16 | 17 | jobs: 18 | - job: BuildBits 19 | displayName: Build and Test solution 20 | timeoutInMinutes: 60 21 | steps: 22 | 23 | # Set Build Version 24 | - script: nbgv cloud 25 | displayName: Set NBGV version 26 | 27 | # Restore solution 28 | - script: dotnet restore -p:Configuration=$(Build.Configuration) 29 | displayName: Restore solution 30 | 31 | # Build solution 32 | - script: dotnet build --no-restore -c $(Build.Configuration) 33 | displayName: Build solution 34 | 35 | # Test solution # 36 | 37 | # Run .NET 8 unit tests 38 | - script: dotnet test --no-build -c $(Build.Configuration) -f net8.0 -l "trx;LogFileName=VSTestResults_net8.0.trx" 39 | displayName: Run .NET 8 unit tests 40 | 41 | # Run .NET 7 unit tests 42 | - script: dotnet test --no-build -c $(Build.Configuration) -f net7.0 -l "trx;LogFileName=VSTestResults_net7.0.trx" 43 | displayName: Run .NET 7 unit tests 44 | 45 | # Run .NET Framework 4.7.2 unit tests 46 | - script: dotnet test --no-build -c $(Build.Configuration) -f net472 -l "trx;LogFileName=VSTestResults_net472.trx" 47 | displayName: Run .NET Framework 4.7.2 unit tests 48 | 49 | # Publish test results 50 | - task: PublishTestResults@2 51 | displayName: Publish test results 52 | inputs: 53 | testResultsFormat: VSTest 54 | testResultsFiles: '**/TestResults/VSTestResults*.trx' 55 | condition: always() 56 | 57 | # Pack solution 58 | - script: dotnet pack --no-build -c $(Build.Configuration) 59 | displayName: Pack solution 60 | 61 | # Sign packages 62 | - pwsh: build/Sign-Package.ps1 63 | displayName: Authenticode sign packages 64 | env: 65 | SignClientUser: $(SignClientUser) 66 | SignClientSecret: $(SignClientSecret) 67 | ArtifactDirectory: bin/nupkg 68 | condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'), ne(variables['SignClientUser'], ''), ne(variables['SignClientSecret'], '')) 69 | 70 | # Publish build artifacts 71 | - publish: bin/nupkg 72 | artifact: Packages 73 | displayName: Publish package artifacts 74 | -------------------------------------------------------------------------------- /build/Community.Toolkit.Common.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Microsoft 5 | Microsoft 6 | .NET Community Toolkit 7 | dotnet;Community;Toolkit 8 | MIT 9 | true 10 | (c) .NET Foundation and Contributors. All rights reserved. 11 | https://github.com/CommunityToolkit/dotnet 12 | https://github.com/CommunityToolkit/dotnet/releases 13 | Icon.png 14 | https://raw.githubusercontent.com/CommunityToolkit/dotnet/main/build/nuget.png 15 | 16 | 17 | 18 | true 19 | 20 | 21 | 22 | true 23 | 12.0 24 | enable 25 | 26 | 31 | $(NoWarn);CS8500 32 | 33 | 34 | 35 | true 36 | $(RepositoryDirectory)toolkit.snk 37 | 002400000480000094000000060200000024000052534131000400000100010041753AF735AE6140C9508567666C51C6AB929806ADB0D210694B30AB142A060237BC741F9682E7D8D4310364B4BBA4EE89CC9D3D5CE7E5583587E8EA44DCA09977996582875E71FB54FA7B170798D853D5D8010B07219633BDB761D01AC924DA44576D6180CDCEAE537973982BB461C541541D58417A3794E34F45E6F2D129E2 38 | 39 | 40 | 41 | $(MSBuildProjectName.Contains('Test')) 42 | False 43 | True 44 | 45 | 46 | 47 | true 48 | true 49 | $(TF_BUILD) 50 | 51 | 52 | -------------------------------------------------------------------------------- /build/Community.Toolkit.Common.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(Product) Asset 5 | 6 | 7 | 8 | $(CommonTags);.NET 9 | $(CommonTags);$(PackageTags) 10 | $(CommonTags) 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /build/Sign-Package.ps1: -------------------------------------------------------------------------------- 1 | 2 | $currentDirectory = split-path $MyInvocation.MyCommand.Definition 3 | 4 | # See if we have the ClientSecret available 5 | if ([string]::IsNullOrEmpty($Env:SignClientSecret)) { 6 | Write-Host "Client Secret not found, not signing packages" 7 | return; 8 | } 9 | 10 | dotnet tool install --tool-path . SignClient 11 | 12 | # Setup Variables we need to pass into the sign client tool 13 | 14 | $appSettings = "$currentDirectory\SignClientSettings.json" 15 | 16 | $nupkgs = Get-ChildItem $Env:ArtifactDirectory\*.nupkg -recurse | Select-Object -ExpandProperty FullName 17 | 18 | foreach ($nupkg in $nupkgs) { 19 | Write-Host "Submitting $nupkg for signing" 20 | 21 | .\SignClient 'sign' -c $appSettings -i $nupkg -r $Env:SignClientUser -s $Env:SignClientSecret -n '.NET Community Toolkit' -d '.NET Community Toolkit' -u 'https://developer.microsoft.com/en-us/windows/uwp-community-toolkit' 22 | if ($LASTEXITCODE -ne 0) { 23 | exit 1 24 | } 25 | Write-Host "Finished signing $nupkg" 26 | } 27 | 28 | Write-Host "Sign-package complete" -------------------------------------------------------------------------------- /build/SignClientSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "SignClient": { 3 | "AzureAd": { 4 | "AADInstance": "https://login.microsoftonline.com/", 5 | "ClientId": "c248d68a-ba6f-4aa9-8a68-71fe872063f8", 6 | "TenantId": "16076fdc-fcc1-4a15-b1ca-32c9a255900e" 7 | }, 8 | "Service": { 9 | "Url": "https://codesign.dotnetfoundation.org/", 10 | "ResourceId": "https://SignService/3c30251f-36f3-490b-a955-520addb85001" 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /build/nuget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/dotnet/657c6971a8d42655c648336b781639ed96c2c49f/build/nuget.png -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "9.0.100", 4 | "rollForward": "latestFeature", 5 | "allowPrerelease": false 6 | } 7 | } -------------------------------------------------------------------------------- /src/CommunityToolkit.Common/CommunityToolkit.Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0;netstandard2.1;net8.0 5 | 6 | 7 | 8 | .NET Community Toolkit - Common 9 | 10 | This package includes .NET helpers such as: 11 | - IncrementalLoadingCollection: Simplifies the definition and usage of collections whose items can be loaded incrementally only when needed by the view. 12 | - String extensions and array extensions: These extensions make working with string and arrays easier. 13 | 14 | Incremental;Loading;Collection;IncrementalLoadingCollection;String;Array;Extensions;Helpers 15 | 16 | 17 | 18 | 19 | 20 | System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute; 21 | System.Diagnostics.CodeAnalysis.NotNullWhenAttribute; 22 | System.Runtime.CompilerServices.SkipLocalsInitAttribute; 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Common/Converters.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Common; 6 | 7 | /// 8 | /// Set of helpers to convert between data types and notations. 9 | /// 10 | public static class Converters 11 | { 12 | /// 13 | /// Translate numeric file size in bytes to a human-readable shorter string format. 14 | /// 15 | /// File size in bytes. 16 | /// Returns file size short string. 17 | public static string ToFileSizeString(long size) 18 | { 19 | if (size < 1024) 20 | { 21 | return size.ToString("F0") + " bytes"; 22 | } 23 | else if ((size >> 10) < 1024) 24 | { 25 | return (size / 1024F).ToString("F1") + " KB"; 26 | } 27 | else if ((size >> 20) < 1024) 28 | { 29 | return ((size >> 10) / 1024F).ToString("F1") + " MB"; 30 | } 31 | else if ((size >> 30) < 1024) 32 | { 33 | return ((size >> 20) / 1024F).ToString("F1") + " GB"; 34 | } 35 | else if ((size >> 40) < 1024) 36 | { 37 | return ((size >> 30) / 1024F).ToString("F1") + " TB"; 38 | } 39 | else if ((size >> 50) < 1024) 40 | { 41 | return ((size >> 40) / 1024F).ToString("F1") + " PB"; 42 | } 43 | else 44 | { 45 | return ((size >> 50) / 1024F).ToString("F1") + " EB"; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Common/Deferred/DeferredCancelEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Common.Deferred; 6 | 7 | /// 8 | /// which can also be canceled. 9 | /// 10 | public class DeferredCancelEventArgs : DeferredEventArgs 11 | { 12 | /// 13 | /// Gets or sets a value indicating whether the event should be canceled. 14 | /// 15 | public bool Cancel { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Common/Deferred/DeferredEventArgs.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.ComponentModel; 7 | 8 | #pragma warning disable CA1001 9 | 10 | namespace CommunityToolkit.Common.Deferred; 11 | 12 | /// 13 | /// which can retrieve a in order to process data asynchronously before an completes and returns to the calling control. 14 | /// 15 | public class DeferredEventArgs : EventArgs 16 | { 17 | /// 18 | /// Gets a new to use in cases where no wish to be provided. 19 | /// 20 | public static new DeferredEventArgs Empty => new(); 21 | 22 | private readonly object eventDeferralLock = new(); 23 | 24 | private EventDeferral? eventDeferral; 25 | 26 | /// 27 | /// Returns an which can be completed when deferred event is ready to continue. 28 | /// 29 | /// instance. 30 | public EventDeferral GetDeferral() 31 | { 32 | lock (this.eventDeferralLock) 33 | { 34 | return this.eventDeferral ??= new EventDeferral(); 35 | } 36 | } 37 | 38 | /// 39 | /// DO NOT USE - This is a support method used by . It is public only for 40 | /// additional usage within extensions for the UWP based TypedEventHandler extensions. 41 | /// 42 | /// Internal EventDeferral reference 43 | [Browsable(false)] 44 | [EditorBrowsable(EditorBrowsableState.Never)] 45 | [Obsolete("This is an internal only method to be used by EventHandler extension classes, public callers should call GetDeferral() instead.")] 46 | public EventDeferral? GetCurrentDeferralAndReset() 47 | { 48 | lock (this.eventDeferralLock) 49 | { 50 | EventDeferral? eventDeferral = this.eventDeferral; 51 | 52 | this.eventDeferral = null; 53 | 54 | return eventDeferral; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Common/Deferred/EventDeferral.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.ComponentModel; 7 | #if NET8_0_OR_GREATER 8 | using System.Runtime.CompilerServices; 9 | #endif 10 | using System.Threading; 11 | using System.Threading.Tasks; 12 | 13 | #pragma warning disable CA1063 14 | 15 | namespace CommunityToolkit.Common.Deferred; 16 | 17 | /// 18 | /// Deferral handle provided by a . 19 | /// 20 | public class EventDeferral : IDisposable 21 | { 22 | #if NET8_0_OR_GREATER 23 | private readonly TaskCompletionSource taskCompletionSource = new(); 24 | #else 25 | private readonly TaskCompletionSource taskCompletionSource = new(); 26 | #endif 27 | 28 | internal EventDeferral() 29 | { 30 | } 31 | 32 | /// 33 | /// Call when finished with the Deferral. 34 | /// 35 | public void Complete() 36 | { 37 | #if NET8_0_OR_GREATER 38 | this.taskCompletionSource.TrySetResult(); 39 | #else 40 | this.taskCompletionSource.TrySetResult(null); 41 | #endif 42 | } 43 | 44 | /// 45 | /// Waits for the to be completed by the event handler. 46 | /// 47 | /// . 48 | /// . 49 | [Browsable(false)] 50 | [EditorBrowsable(EditorBrowsableState.Never)] 51 | [Obsolete("This is an internal only method to be used by EventHandler extension classes, public callers should call GetDeferral() instead on the DeferredEventArgs.")] 52 | public async Task WaitForCompletion(CancellationToken cancellationToken) 53 | { 54 | using (cancellationToken.Register( 55 | #if NET8_0_OR_GREATER 56 | callback: static obj => Unsafe.As(obj!).taskCompletionSource.TrySetCanceled(), 57 | #else 58 | callback: static obj => ((EventDeferral)obj).taskCompletionSource.TrySetCanceled(), 59 | #endif 60 | state: this)) 61 | { 62 | #if NET8_0_OR_GREATER 63 | await this.taskCompletionSource.Task; 64 | #else 65 | _ = await this.taskCompletionSource.Task; 66 | #endif 67 | } 68 | } 69 | 70 | /// 71 | public void Dispose() 72 | { 73 | Complete(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Common/Helpers/ObjectStorage/DirectoryItemType.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Common.Helpers; 6 | 7 | /// 8 | /// Represents the types of items available in a directory. 9 | /// 10 | public enum DirectoryItemType 11 | { 12 | /// 13 | /// The item is neither a file or a folder. 14 | /// 15 | None, 16 | 17 | /// 18 | /// Represents a file type item. 19 | /// 20 | File, 21 | 22 | /// 23 | /// Represents a folder type item. 24 | /// 25 | Folder 26 | } 27 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Common/Helpers/ObjectStorage/IObjectSerializer.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Common.Helpers; 6 | 7 | /// 8 | /// A basic serialization service. 9 | /// 10 | public interface IObjectSerializer 11 | { 12 | /// 13 | /// Serialize an object into a string. It is recommended to use strings as the final format for objects. 14 | /// 15 | /// The type of the object to serialize. 16 | /// The object to serialize. 17 | /// The serialized object. 18 | string? Serialize(T value); 19 | 20 | /// 21 | /// Deserialize string into an object of the given type. 22 | /// 23 | /// The type of the deserialized object. 24 | /// The string to deserialize. 25 | /// The deserialized object. 26 | T Deserialize(string value); 27 | } 28 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Common/Helpers/ObjectStorage/ISettingsStorageHelper.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Helpers; 6 | 7 | /// 8 | /// Service interface used to store data using key value pairs. 9 | /// 10 | /// The type of keys to use for accessing values. 11 | public interface ISettingsStorageHelper 12 | where TKey : notnull 13 | { 14 | /// 15 | /// Retrieves a single item by its key. 16 | /// 17 | /// Type of object retrieved. 18 | /// Key of the object. 19 | /// The object for key. 20 | /// A boolean indicator of success. 21 | bool TryRead(TKey key, out TValue? value); 22 | 23 | /// 24 | /// Saves a single item by its key. 25 | /// 26 | /// Type of object saved. 27 | /// Key of the value saved. 28 | /// Object to save. 29 | void Save(TKey key, TValue value); 30 | 31 | /// 32 | /// Deletes a single item by its key. 33 | /// 34 | /// Key of the object. 35 | /// A boolean indicator of success. 36 | bool TryDelete(TKey key); 37 | 38 | /// 39 | /// Clear all keys and values from the settings store. 40 | /// 41 | void Clear(); 42 | } 43 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Common/Helpers/ObjectStorage/SystemSerializer.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace CommunityToolkit.Common.Helpers; 8 | 9 | /// 10 | /// A bare-bones serializer which knows how to deal with primitive types and strings only. 11 | /// It is recommended for more complex scenarios to implement your own based on System.Text.Json, Newtonsoft.Json, or DataContractJsonSerializer see https://aka.ms/wct/storagehelper-migration 12 | /// 13 | public class SystemSerializer : IObjectSerializer 14 | { 15 | /// 16 | /// Take a primitive value from storage and return it as the requested type using the API. 17 | /// 18 | /// Type to convert value to. 19 | /// Value from storage to convert. 20 | /// Deserialized value or default value. 21 | public T Deserialize(string value) 22 | { 23 | if (typeof(T).IsPrimitive || typeof(T) == typeof(string)) 24 | { 25 | return (T)Convert.ChangeType(value, typeof(T)); 26 | } 27 | 28 | throw new NotSupportedException("This serializer can only handle primitive types and strings. Please implement your own IObjectSerializer for more complex scenarios."); 29 | } 30 | 31 | /// 32 | /// Returns the value so that it can be serialized directly. 33 | /// 34 | /// Type to serialize from. 35 | /// Value to serialize. 36 | /// String representation of value. 37 | public string? Serialize(T value) 38 | { 39 | return value?.ToString(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Common/IncrementalLoadingCollection/IIncrementalSource.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace CommunityToolkit.Common.Collections; 10 | 11 | /// 12 | /// This interface represents a data source whose items can be loaded incrementally. 13 | /// 14 | /// Type of collection element. 15 | public interface IIncrementalSource 16 | { 17 | /// 18 | /// This method is invoked every time the view need to show more items. Retrieves items based on and arguments. 19 | /// 20 | /// 21 | /// The zero-based index of the page that corresponds to the items to retrieve. 22 | /// 23 | /// 24 | /// The number of items to retrieve for the specified . 25 | /// 26 | /// 27 | /// Used to propagate notification that operation should be canceled. 28 | /// 29 | /// 30 | /// Returns a collection of . 31 | /// 32 | Task> GetPagedItemsAsync(int pageIndex, int pageSize, CancellationToken cancellationToken = default); 33 | } 34 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Diagnostics/Generated/Guard.md: -------------------------------------------------------------------------------- 1 | # T4 templates and generated APIs 2 | 3 | This folder contains a number of template files (with the `.tt` or `.ttinclude` extensions) and the generated `.g.cs` files generated by those templates. The template files use the T4 format, which is natively supported by Visual Studio (more info is available [here](https://learn.microsoft.com/visualstudio/modeling/code-generation-and-t4-text-templates)). 4 | 5 | ## Why is this needed? 6 | 7 | There are a few reasons why T4 templates are used for the `Guard` class: 8 | 9 | - Especially when many overloads are available for an API, using templates makes it much easier to maintain code and spot mistakes, as the actual number of lines of code to review is much smaller: it's just the same code from each template! 10 | - Using type-specific overloads instead of generic methods can result in faster code. For instance, T4 templates are used to generate overloads for comparison APIs (eg. `Guard.IsGreaterThan(int, int, string)`). This results in more compact and optimized code as opposed to a generic method using `where T : IComparable` as type constraint. 11 | - In some cases, using generic methods just isn't possible. For instance, types like `Span` and `ReadOnlySpan` can't be used as generic type parameters, and even if that had been possible, they don't implement an interface we could use in the generic type constraint. Using T4 templates solves this issue, as we can just have specialized method for each supported type or collection type. 12 | 13 | ## How to make changes 14 | 15 | If you need to change an API that is declared in a template, or to add a new one, just edit the right `.tt` file and save it: Visual Studio will take care of updating the generated `.g.cs` file automatically. Don't make changes to those generated `.g.cs` files directly, as those will be overwritten as soon as their source template is updated. 16 | 17 | Note that all the `.g.cs` files are checked in into the repository, so if you do make changes to a template file, make sure to also include the updated `.g.cs` file in your commits. 18 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Diagnostics/Generated/TypeInfo.g.cs: -------------------------------------------------------------------------------- 1 | // ===================== 2 | // Auto generated file 3 | // ===================== 4 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Diagnostics/Internals/Guard.Collection.Generic.ThrowHelper.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Diagnostics.CodeAnalysis; 7 | 8 | namespace CommunityToolkit.Diagnostics; 9 | 10 | /// 11 | partial class Guard 12 | { 13 | /// 14 | partial class ThrowHelper 15 | { 16 | /// 17 | /// Throws an when fails. 18 | /// 19 | /// The item of items in the input instance. 20 | /// This method is needed because can't be used as a generic type parameter. 21 | [DoesNotReturn] 22 | public static void ThrowArgumentExceptionForIsNotEmptyWithSpan(string name) 23 | { 24 | throw new ArgumentException($"Parameter {AssertString(name)} ({typeof(Span).ToTypeString()}) must not be empty.", name); 25 | } 26 | 27 | /// 28 | /// Throws an when fails. 29 | /// 30 | /// The item of items in the input instance. 31 | /// This method is needed because can't be used as a generic type parameter. 32 | [DoesNotReturn] 33 | public static void ThrowArgumentExceptionForIsNotEmptyWithReadOnlySpan(string name) 34 | { 35 | throw new ArgumentException($"Parameter {AssertString(name)} ({typeof(ReadOnlySpan).ToTypeString()}) must not be empty.", name); 36 | } 37 | 38 | /// 39 | /// Throws an when (or an overload) fails. 40 | /// 41 | /// The item of items in the input collection. 42 | [DoesNotReturn] 43 | public static void ThrowArgumentExceptionForIsNotEmpty(string name) 44 | { 45 | throw new ArgumentException($"Parameter {AssertString(name)} ({typeof(T).ToTypeString()}) must not be empty.", name); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Diagnostics/Internals/Guard.IO.ThrowHelper.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Diagnostics.CodeAnalysis; 7 | using System.IO; 8 | 9 | namespace CommunityToolkit.Diagnostics; 10 | 11 | /// 12 | partial class Guard 13 | { 14 | /// 15 | partial class ThrowHelper 16 | { 17 | /// 18 | /// Throws an when fails. 19 | /// 20 | [DoesNotReturn] 21 | public static void ThrowArgumentExceptionForCanRead(Stream stream, string name) 22 | { 23 | throw new ArgumentException($"Stream {AssertString(name)} ({stream.GetType().ToTypeString()}) doesn't support reading.", name); 24 | } 25 | 26 | /// 27 | /// Throws an when fails. 28 | /// 29 | [DoesNotReturn] 30 | public static void ThrowArgumentExceptionForCanWrite(Stream stream, string name) 31 | { 32 | throw new ArgumentException($"Stream {AssertString(name)} ({stream.GetType().ToTypeString()}) doesn't support writing.", name); 33 | } 34 | 35 | /// 36 | /// Throws an when fails. 37 | /// 38 | [DoesNotReturn] 39 | public static void ThrowArgumentExceptionForCanSeek(Stream stream, string name) 40 | { 41 | throw new ArgumentException($"Stream {AssertString(name)} ({stream.GetType().ToTypeString()}) doesn't support seeking.", name); 42 | } 43 | 44 | /// 45 | /// Throws an when fails. 46 | /// 47 | [DoesNotReturn] 48 | public static void ThrowArgumentExceptionForIsAtStartPosition(Stream stream, string name) 49 | { 50 | throw new ArgumentException($"Stream {AssertString(name)} ({stream.GetType().ToTypeString()}) must be at position {AssertString(0)}, was at {AssertString(stream.Position)}.", name); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Buffers/Enums/AllocationMode.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.HighPerformance.Buffers; 6 | 7 | /// 8 | /// An that indicates a mode to use when allocating buffers. 9 | /// 10 | public enum AllocationMode 11 | { 12 | /// 13 | /// The default allocation mode for pooled memory (rented buffers are not cleared). 14 | /// 15 | Default, 16 | 17 | /// 18 | /// Clear pooled buffers when renting them. 19 | /// 20 | Clear 21 | } 22 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Buffers/Interfaces/IBuffer{T}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Buffers; 7 | 8 | namespace CommunityToolkit.HighPerformance.Buffers; 9 | 10 | /// 11 | /// An interface that expands with the ability to also inspect 12 | /// the written data, and to reset the underlying buffer to write again from the start. 13 | /// 14 | /// The type of items in the current buffer. 15 | public interface IBuffer : IBufferWriter 16 | { 17 | /// 18 | /// Gets the data written to the underlying buffer so far, as a . 19 | /// 20 | ReadOnlyMemory WrittenMemory { get; } 21 | 22 | /// 23 | /// Gets the data written to the underlying buffer so far, as a . 24 | /// 25 | ReadOnlySpan WrittenSpan { get; } 26 | 27 | /// 28 | /// Gets the amount of data written to the underlying buffer so far. 29 | /// 30 | int WrittenCount { get; } 31 | 32 | /// 33 | /// Gets the total amount of space within the underlying buffer. 34 | /// 35 | int Capacity { get; } 36 | 37 | /// 38 | /// Gets the amount of space available that can still be written into without forcing the underlying buffer to grow. 39 | /// 40 | int FreeCapacity { get; } 41 | 42 | /// 43 | /// Clears the data written to the underlying buffer. 44 | /// 45 | /// 46 | /// You must clear the instance before trying to re-use it. 47 | /// 48 | void Clear(); 49 | } 50 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Buffers/Internals/Interfaces/IMemoryManager.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Buffers; 7 | 8 | namespace CommunityToolkit.HighPerformance.Buffers.Internals.Interfaces; 9 | 10 | /// 11 | /// An interface for a instance that can reinterpret its underlying data. 12 | /// 13 | internal interface IMemoryManager 14 | { 15 | /// 16 | /// Creates a new that reinterprets the underlying data for the current instance. 17 | /// 18 | /// The target type to cast the items to. 19 | /// The starting offset within the data store. 20 | /// The original used length for the data store. 21 | /// A new instance of the specified type, reinterpreting the current items. 22 | Memory GetMemory(int offset, int length) 23 | where T : unmanaged; 24 | } 25 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Buffers/Views/MemoryDebugView{T}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace CommunityToolkit.HighPerformance.Buffers.Views; 8 | 9 | /// 10 | /// A debug proxy used to display items in a 1D layout. 11 | /// 12 | /// The type of items to display. 13 | internal sealed class MemoryDebugView 14 | { 15 | /// 16 | /// Initializes a new instance of the class with the specified parameters. 17 | /// 18 | /// The input instance with the items to display. 19 | public MemoryDebugView(ArrayPoolBufferWriter? arrayPoolBufferWriter) 20 | { 21 | this.Items = arrayPoolBufferWriter?.WrittenSpan.ToArray(); 22 | } 23 | 24 | /// 25 | /// Initializes a new instance of the class with the specified parameters. 26 | /// 27 | /// The input instance with the items to display. 28 | public MemoryDebugView(MemoryBufferWriter? memoryBufferWriter) 29 | { 30 | this.Items = memoryBufferWriter?.WrittenSpan.ToArray(); 31 | } 32 | 33 | /// 34 | /// Initializes a new instance of the class with the specified parameters. 35 | /// 36 | /// The input instance with the items to display. 37 | public MemoryDebugView(MemoryOwner? memoryOwner) 38 | { 39 | this.Items = memoryOwner?.Span.ToArray(); 40 | } 41 | 42 | /// 43 | /// Initializes a new instance of the class with the specified parameters. 44 | /// 45 | /// The input instance with the items to display. 46 | public MemoryDebugView(SpanOwner spanOwner) 47 | { 48 | this.Items = spanOwner.Span.ToArray(); 49 | } 50 | 51 | /// 52 | /// Gets the items to display for the current instance 53 | /// 54 | [DebuggerBrowsable(DebuggerBrowsableState.Collapsed)] 55 | public T[]? Items { get; } 56 | } 57 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Extensions/ArrayPoolBufferWriterExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO; 6 | using System.Runtime.CompilerServices; 7 | using CommunityToolkit.HighPerformance.Buffers; 8 | using CommunityToolkit.HighPerformance.Streams; 9 | 10 | namespace CommunityToolkit.HighPerformance; 11 | 12 | /// 13 | /// Helpers for working with the type. 14 | /// 15 | public static class ArrayPoolBufferWriterExtensions 16 | { 17 | /// 18 | /// Returns a that can be used to write to a target an of instance. 19 | /// 20 | /// The target instance. 21 | /// A wrapping and writing data to its underlying buffer. 22 | /// The returned can only be written to and does not support seeking. 23 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 24 | public static Stream AsStream(this ArrayPoolBufferWriter writer) 25 | { 26 | return new IBufferWriterStream(new ArrayBufferWriterOwner(writer)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Extensions/HashCodeExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Runtime.CompilerServices; 7 | using CommunityToolkit.HighPerformance.Helpers; 8 | 9 | namespace CommunityToolkit.HighPerformance; 10 | 11 | /// 12 | /// Helpers for working with the type. 13 | /// 14 | public static class HashCodeExtensions 15 | { 16 | /// 17 | /// Adds a sequence of values to the hash code. 18 | /// 19 | /// The type of elements in the input instance. 20 | /// The input instance. 21 | /// The input instance. 22 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 23 | public static void Add(ref this HashCode hashCode, ReadOnlySpan span) 24 | where T : notnull 25 | { 26 | int hash = HashCode.CombineValues(span); 27 | 28 | hashCode.Add(hash); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Extensions/IMemoryOwnerExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Buffers; 7 | using System.IO; 8 | using System.Runtime.CompilerServices; 9 | using MemoryStream = CommunityToolkit.HighPerformance.Streams.MemoryStream; 10 | 11 | namespace CommunityToolkit.HighPerformance; 12 | 13 | /// 14 | /// Helpers for working with the type. 15 | /// 16 | public static class IMemoryOwnerExtensions 17 | { 18 | /// 19 | /// Returns a wrapping the contents of the given of instance. 20 | /// 21 | /// The input of instance. 22 | /// A wrapping the data within . 23 | /// 24 | /// The caller does not need to track the lifetime of the input of 25 | /// instance, as the returned will take care of disposing that buffer when it is closed. 26 | /// 27 | /// Thrown when has an invalid data store. 28 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 29 | public static Stream AsStream(this IMemoryOwner memoryOwner) 30 | { 31 | return MemoryStream.Create(memoryOwner); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Extensions/ListExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | #if NET6_0_OR_GREATER 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Runtime.CompilerServices; 10 | using System.Runtime.InteropServices; 11 | 12 | namespace CommunityToolkit.HighPerformance; 13 | 14 | /// 15 | /// Helpers for working with the type. 16 | /// 17 | public static class ListExtensions 18 | { 19 | /// 20 | /// Creates a new over an input instance. 21 | /// 22 | /// The type of elements in the input instance. 23 | /// The input instance. 24 | /// A instance with the values of . 25 | /// 26 | /// Note that the returned is only guaranteed to be valid as long as the items within 27 | /// are not modified. Doing so might cause the to swap its 28 | /// internal buffer, causing the returned to become out of date. That means that in this 29 | /// scenario, the would end up wrapping an array no longer in use. Always make sure to use 30 | /// the returned while the target is not modified. 31 | /// 32 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 33 | public static Span AsSpan(this List? list) 34 | { 35 | return CollectionsMarshal.AsSpan(list); 36 | } 37 | } 38 | 39 | #endif -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Extensions/ReadOnlySequenceExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.HighPerformance.Streams; 6 | using System; 7 | using System.Buffers; 8 | using System.IO; 9 | using System.Runtime.CompilerServices; 10 | 11 | namespace CommunityToolkit.HighPerformance; 12 | 13 | /// 14 | /// Helpers for working with the type. 15 | /// 16 | public static class ReadOnlySequenceExtensions 17 | { 18 | /// 19 | /// Returns a wrapping the contents of the given of instance. 20 | /// 21 | /// The input of instance. 22 | /// A wrapping the data within . 23 | /// 24 | /// Since this method only receives a instance, which does not track 25 | /// the lifetime of its underlying buffer, it is responsibility of the caller to manage that. 26 | /// In particular, the caller must ensure that the target buffer is not disposed as long 27 | /// as the returned is in use, to avoid unexpected issues. 28 | /// 29 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 30 | public static Stream AsStream(this ReadOnlySequence sequence) 31 | { 32 | return ReadOnlySequenceStream.Create(sequence); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Helpers/Internals/BitOperations.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | #if !NET6_0_OR_GREATER 6 | 7 | using System.Runtime.CompilerServices; 8 | 9 | namespace CommunityToolkit.HighPerformance.Helpers.Internals; 10 | 11 | /// 12 | /// Utility methods for intrinsic bit-twiddling operations. The methods use hardware intrinsics 13 | /// when available on the underlying platform, otherwise they use optimized software fallbacks. 14 | /// 15 | internal static class BitOperations 16 | { 17 | /// 18 | /// Round the given integral value up to a power of 2. 19 | /// 20 | /// The value. 21 | /// 22 | /// The smallest power of 2 which is greater than or equal to . 23 | /// If is 0 or the result overflows, returns 0. 24 | /// 25 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 26 | public static unsafe uint RoundUpToPowerOf2(uint value) 27 | { 28 | // Based on https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 29 | --value; 30 | value |= value >> 1; 31 | value |= value >> 2; 32 | value |= value >> 4; 33 | value |= value >> 8; 34 | value |= value >> 16; 35 | 36 | return value + 1; 37 | } 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Memory/Views/MemoryDebugView2D{T}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | 7 | namespace CommunityToolkit.HighPerformance.Memory.Views; 8 | 9 | /// 10 | /// A debug proxy used to display items in a 2D layout. 11 | /// 12 | /// The type of items to display. 13 | internal sealed class MemoryDebugView2D 14 | { 15 | /// 16 | /// Initializes a new instance of the class with the specified parameters. 17 | /// 18 | /// The input instance with the items to display. 19 | public MemoryDebugView2D(Memory2D memory) 20 | { 21 | this.Items = memory.ToArray(); 22 | } 23 | 24 | /// 25 | /// Initializes a new instance of the class with the specified parameters. 26 | /// 27 | /// The input instance with the items to display. 28 | public MemoryDebugView2D(ReadOnlyMemory2D memory) 29 | { 30 | this.Items = memory.ToArray(); 31 | } 32 | 33 | /// 34 | /// Initializes a new instance of the class with the specified parameters. 35 | /// 36 | /// The input instance with the items to display. 37 | public MemoryDebugView2D(Span2D span) 38 | { 39 | this.Items = span.ToArray(); 40 | } 41 | 42 | /// 43 | /// Initializes a new instance of the class with the specified parameters. 44 | /// 45 | /// The input instance with the items to display. 46 | public MemoryDebugView2D(ReadOnlySpan2D span) 47 | { 48 | this.Items = span.ToArray(); 49 | } 50 | 51 | /// 52 | /// Gets the items to display for the current instance 53 | /// 54 | [DebuggerBrowsable(DebuggerBrowsableState.Collapsed)] 55 | public T[,]? Items { get; } 56 | } 57 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Ref{T}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | #if NET7_0_OR_GREATER 6 | 7 | using System.Runtime.CompilerServices; 8 | 9 | namespace CommunityToolkit.HighPerformance; 10 | 11 | /// 12 | /// A that can store a reference to a value of a specified type. 13 | /// 14 | /// The type of value to reference. 15 | public readonly ref struct Ref 16 | { 17 | /// 18 | /// The reference to the target value. 19 | /// 20 | private readonly ref T value; 21 | 22 | /// 23 | /// Initializes a new instance of the struct. 24 | /// 25 | /// The reference to the target value. 26 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 27 | public Ref(ref T value) 28 | { 29 | this.value = ref value; 30 | } 31 | 32 | /// 33 | /// Initializes a new instance of the struct. 34 | /// 35 | /// The pointer to the target value. 36 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 37 | public unsafe Ref(void* pointer) 38 | : this(ref Unsafe.AsRef(pointer)) 39 | { 40 | } 41 | 42 | /// 43 | /// Gets the reference represented by the current instance. 44 | /// 45 | public ref T Value 46 | { 47 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 48 | get => ref this.value; 49 | } 50 | 51 | /// 52 | /// Implicitly gets the value from a given instance. 53 | /// 54 | /// The input instance. 55 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 56 | public static implicit operator T(Ref reference) 57 | { 58 | return reference.Value; 59 | } 60 | } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Streams/IBufferWriterStream{TWriter}.Memory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | #if NETSTANDARD2_1_OR_GREATER 6 | 7 | using System; 8 | using System.IO; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | 12 | namespace CommunityToolkit.HighPerformance.Streams; 13 | 14 | /// 15 | partial class IBufferWriterStream 16 | { 17 | /// 18 | public override void CopyTo(Stream destination, int bufferSize) 19 | { 20 | throw MemoryStream.GetNotSupportedException(); 21 | } 22 | 23 | /// 24 | public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) 25 | { 26 | throw MemoryStream.GetNotSupportedException(); 27 | } 28 | 29 | /// 30 | public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) 31 | { 32 | if (cancellationToken.IsCancellationRequested) 33 | { 34 | return new(Task.FromCanceled(cancellationToken)); 35 | } 36 | 37 | try 38 | { 39 | Write(buffer.Span); 40 | 41 | return default; 42 | } 43 | catch (OperationCanceledException e) 44 | { 45 | return new(Task.FromCanceled(e.CancellationToken)); 46 | } 47 | catch (Exception e) 48 | { 49 | return new(Task.FromException(e)); 50 | } 51 | } 52 | 53 | /// 54 | public override int Read(Span buffer) 55 | { 56 | throw MemoryStream.GetNotSupportedException(); 57 | } 58 | 59 | /// 60 | public override void Write(ReadOnlySpan buffer) 61 | { 62 | MemoryStream.ValidateDisposed(this.disposed); 63 | 64 | Span destination = this.bufferWriter.GetSpan(buffer.Length); 65 | 66 | if (!buffer.TryCopyTo(destination)) 67 | { 68 | MemoryStream.ThrowArgumentExceptionForEndOfStreamOnWrite(); 69 | } 70 | 71 | this.bufferWriter.Advance(buffer.Length); 72 | } 73 | } 74 | 75 | #endif -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Streams/IMemoryOwnerStream{TSource}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Buffers; 7 | using System.IO; 8 | 9 | namespace CommunityToolkit.HighPerformance.Streams; 10 | 11 | /// 12 | /// A implementation wrapping an of instance. 13 | /// 14 | /// The type of source to use for the underlying data. 15 | internal sealed class IMemoryOwnerStream : MemoryStream 16 | where TSource : struct, ISpanOwner 17 | { 18 | /// 19 | /// The instance currently in use. 20 | /// 21 | private readonly IDisposable disposable; 22 | 23 | /// 24 | /// Initializes a new instance of the class. 25 | /// 26 | /// The input instance to use. 27 | /// The instance currently in use. 28 | public IMemoryOwnerStream(TSource source, IDisposable disposable) 29 | : base(source, false) 30 | { 31 | this.disposable = disposable; 32 | } 33 | 34 | /// 35 | protected override void Dispose(bool disposing) 36 | { 37 | base.Dispose(disposing); 38 | 39 | this.disposable.Dispose(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Streams/Sources/ArrayBufferWriterOwner.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Buffers; 7 | using System.Runtime.CompilerServices; 8 | using CommunityToolkit.HighPerformance.Buffers; 9 | 10 | namespace CommunityToolkit.HighPerformance.Streams; 11 | 12 | /// 13 | /// An implementation wrapping an instance. 14 | /// 15 | internal readonly struct ArrayBufferWriterOwner : IBufferWriter 16 | { 17 | /// 18 | /// The wrapped array. 19 | /// 20 | private readonly ArrayPoolBufferWriter writer; 21 | 22 | /// 23 | /// Initializes a new instance of the struct. 24 | /// 25 | /// The wrapped instance. 26 | public ArrayBufferWriterOwner(ArrayPoolBufferWriter writer) 27 | { 28 | this.writer = writer; 29 | } 30 | 31 | /// 32 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 33 | public void Advance(int count) 34 | { 35 | this.writer.Advance(count); 36 | } 37 | 38 | /// 39 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 40 | public Memory GetMemory(int sizeHint = 0) 41 | { 42 | return this.writer.GetMemory(sizeHint); 43 | } 44 | 45 | /// 46 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 47 | public Span GetSpan(int sizeHint = 0) 48 | { 49 | return this.writer.GetSpan(sizeHint); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Streams/Sources/IBufferWriterOwner.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Buffers; 7 | using System.Runtime.CompilerServices; 8 | using CommunityToolkit.HighPerformance.Buffers; 9 | 10 | namespace CommunityToolkit.HighPerformance.Streams; 11 | 12 | /// 13 | /// An implementation wrapping an instance. 14 | /// 15 | internal readonly struct IBufferWriterOwner : IBufferWriter 16 | { 17 | /// 18 | /// The wrapped array. 19 | /// 20 | private readonly IBufferWriter writer; 21 | 22 | /// 23 | /// Initializes a new instance of the struct. 24 | /// 25 | /// The wrapped instance. 26 | public IBufferWriterOwner(IBufferWriter writer) 27 | { 28 | this.writer = writer; 29 | } 30 | 31 | /// 32 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 33 | public void Advance(int count) 34 | { 35 | this.writer.Advance(count); 36 | } 37 | 38 | /// 39 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 40 | public Memory GetMemory(int sizeHint = 0) 41 | { 42 | return this.writer.GetMemory(sizeHint); 43 | } 44 | 45 | /// 46 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 47 | public Span GetSpan(int sizeHint = 0) 48 | { 49 | return this.writer.GetSpan(sizeHint); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/CommunityToolkit.HighPerformance/Streams/Sources/Interfaces/ISpanOwner.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace CommunityToolkit.HighPerformance.Streams; 8 | 9 | /// 10 | /// An interface for types acting as sources for instances. 11 | /// 12 | internal interface ISpanOwner 13 | { 14 | /// 15 | /// Gets the length of the underlying memory area. 16 | /// 17 | int Length { get; } 18 | 19 | /// 20 | /// Gets a instance wrapping the underlying memory area. 21 | /// 22 | Span Span { get; } 23 | 24 | /// 25 | /// Gets a instance wrapping the underlying memory area. 26 | /// 27 | Memory Memory { get; } 28 | } 29 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.CodeFixers.Roslyn4001/CommunityToolkit.Mvvm.CodeFixers.Roslyn4001.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.CodeFixers.Roslyn4120/CommunityToolkit.Mvvm.CodeFixers.Roslyn4120.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.CodeFixers/CommunityToolkit.Mvvm.CodeFixers.projitems: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | a2ebda90-b720-430d-83f5-c6bcc355232c 7 | 8 | 9 | CommunityToolkit.Mvvm.CodeFixers 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.CodeFixers/CommunityToolkit.Mvvm.CodeFixers.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | a2ebda90-b720-430d-83f5-c6bcc355232c 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators.Roslyn4001/CommunityToolkit.Mvvm.SourceGenerators.Roslyn4001.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators.Roslyn4031/CommunityToolkit.Mvvm.SourceGenerators.Roslyn4031.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators.Roslyn4120/CommunityToolkit.Mvvm.SourceGenerators.Roslyn4120.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/AnalyzerReleases.Unshipped.md: -------------------------------------------------------------------------------- 1 | ; Unshipped analyzer release 2 | ; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md 3 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/CommunityToolkit.Mvvm.SourceGenerators.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5e7f1212-a54b-40ca-98c5-1ff5cd1a1638 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/INotifyPropertyChangedInfo.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Mvvm.SourceGenerators.ComponentModel.Models; 6 | 7 | /// 8 | /// A model with gathered info on a given INotifyPropertyChangedAttribute instance. 9 | /// 10 | /// Whether to also generate helper methods in the target type. 11 | public sealed record INotifyPropertyChangedInfo(bool IncludeAdditionalHelperMethods); 12 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/ObservableRecipientInfo.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Mvvm.SourceGenerators.ComponentModel.Models; 6 | 7 | /// 8 | /// A model with gathered info on a given ObservableRecipientAttribute instance. 9 | /// 10 | /// The type name of the type being annotated. 11 | /// Whether or not the target type has explicit constructors. 12 | /// Whether or not the target type is abstract. 13 | /// Whether or not the target type inherits from ObservableValidator. 14 | /// Whether or not the RequiresUnreferencedCodeAttribute type is available. 15 | /// Whether the target type has a custom OnActivated() method. 16 | /// Whether the target type has a custom OnDeactivated() method. 17 | public sealed record ObservableRecipientInfo( 18 | string TypeName, 19 | bool HasExplicitConstructors, 20 | bool IsAbstract, 21 | bool IsObservableValidator, 22 | bool IsRequiresUnreferencedCodeAttributeAvailable, 23 | bool HasOnActivatedMethod, 24 | bool HasOnDeactivatedMethod); 25 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/ValidationInfo.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Mvvm.SourceGenerators.Helpers; 6 | 7 | namespace CommunityToolkit.Mvvm.SourceGenerators.ComponentModel.Models; 8 | 9 | /// 10 | /// A model with gathered info on all validatable properties in a given type. 11 | /// 12 | /// The filename hint for the current type. 13 | /// The fully qualified type name of the target type. 14 | /// The name of validatable properties. 15 | internal sealed record ValidationInfo(string FilenameHint, string TypeName, EquatableArray PropertyNames); 16 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/SuppressionDescriptors.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.CodeAnalysis; 6 | 7 | #pragma warning disable IDE0090 // Use 'new SuppressionDescriptor(...)' 8 | 9 | namespace CommunityToolkit.Mvvm.SourceGenerators.Diagnostics; 10 | 11 | /// 12 | /// A container for all instances for suppressed diagnostics by analyzers in this project. 13 | /// 14 | internal static class SuppressionDescriptors 15 | { 16 | /// 17 | /// Gets a for a field using [ObservableProperty] with an attribute list targeting a property. 18 | /// 19 | public static readonly SuppressionDescriptor PropertyAttributeListForObservablePropertyField = new SuppressionDescriptor( 20 | id: "MVVMTKSPR0001", 21 | suppressedDiagnosticId: "CS0657", 22 | justification: "Fields using [ObservableProperty] can use [property:], [set:] and [set:] attribute lists to forward attributes to the generated properties"); 23 | 24 | /// 25 | /// Gets a for a field using [ObservableProperty] with an attribute list targeting a get or set accessor. 26 | /// 27 | public static readonly SuppressionDescriptor PropertyAttributeListForObservablePropertyFieldAccessors = new SuppressionDescriptor( 28 | id: "MVVMTKSPR0001", 29 | suppressedDiagnosticId: "CS0658", 30 | justification: "Fields using [ObservableProperty] can use [property:], [set:] and [set:] attribute lists to forward attributes to the generated properties"); 31 | 32 | /// 33 | /// Gets a for a method using [RelayCommand] with an attribute list targeting a field or property. 34 | /// 35 | public static readonly SuppressionDescriptor FieldOrPropertyAttributeListForRelayCommandMethod = new SuppressionDescriptor( 36 | id: "MVVMTKSPR0002", 37 | suppressedDiagnosticId: "CS0657", 38 | justification: "Methods using [RelayCommand] can use [field:] and [property:] attribute lists to forward attributes to the generated fields and properties"); 39 | } 40 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Extensions/AccessibilityExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; 8 | 9 | namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions; 10 | 11 | /// 12 | /// Extension methods for the type. 13 | /// 14 | internal static class AccessibilityExtensions 15 | { 16 | /// 17 | /// Converts a given value to the equivalent ."/> 18 | /// 19 | /// The input value to convert. 20 | /// The representing the modifiers for . 21 | public static SyntaxTokenList ToSyntaxTokenList(this Accessibility accessibility) 22 | { 23 | return accessibility switch 24 | { 25 | Accessibility.NotApplicable => TokenList(), 26 | Accessibility.Private => TokenList(Token(SyntaxKind.PrivateKeyword)), 27 | Accessibility.ProtectedAndInternal => TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ProtectedKeyword)), 28 | Accessibility.Protected => TokenList(Token(SyntaxKind.ProtectedKeyword)), 29 | Accessibility.Internal => TokenList(Token(SyntaxKind.InternalKeyword)), 30 | Accessibility.ProtectedOrInternal => TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.InternalKeyword)), 31 | Accessibility.Public => TokenList(Token(SyntaxKind.PublicKeyword)), 32 | _ => TokenList() 33 | }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Extensions/GeneratorAttributeSyntaxContextWithOptions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Immutable; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.Diagnostics; 8 | 9 | namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions; 10 | 11 | /// 12 | /// 13 | /// 14 | /// The original value. 15 | /// The original value. 16 | internal readonly struct GeneratorAttributeSyntaxContextWithOptions( 17 | GeneratorAttributeSyntaxContext syntaxContext, 18 | AnalyzerConfigOptions globalOptions) 19 | { 20 | /// 21 | public SyntaxNode TargetNode { get; } = syntaxContext.TargetNode; 22 | 23 | /// 24 | public ISymbol TargetSymbol { get; } = syntaxContext.TargetSymbol; 25 | 26 | /// 27 | public SemanticModel SemanticModel { get; } = syntaxContext.SemanticModel; 28 | 29 | /// 30 | public ImmutableArray Attributes { get; } = syntaxContext.Attributes; 31 | 32 | /// 33 | public AnalyzerConfigOptions GlobalOptions { get; } = globalOptions; 34 | } 35 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Extensions/MemberDeclarationSyntaxExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using Microsoft.CodeAnalysis.CSharp.Syntax; 8 | using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; 9 | 10 | namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions; 11 | 12 | /// 13 | /// Extension methods for the type. 14 | /// 15 | internal static class MemberDeclarationSyntaxExtensions 16 | { 17 | /// 18 | /// Replaces a specific modifier. 19 | /// 20 | /// The input instance. 21 | /// The target modifier kind to replace. 22 | /// The new modifier kind to add or replace. 23 | /// A instance with the target modifier. 24 | public static MemberDeclarationSyntax ReplaceModifier(this MemberDeclarationSyntax memberDeclaration, SyntaxKind oldKind, SyntaxKind newKind) 25 | { 26 | int index = memberDeclaration.Modifiers.IndexOf(oldKind); 27 | 28 | if (index != -1) 29 | { 30 | return memberDeclaration.WithModifiers(memberDeclaration.Modifiers.Replace(memberDeclaration.Modifiers[index], Token(newKind))); 31 | } 32 | 33 | return memberDeclaration; 34 | } 35 | 36 | /// 37 | /// Removes a specific modifier. 38 | /// 39 | /// The input instance. 40 | /// The modifier kind to remove. 41 | /// A instance without the specified modifier. 42 | public static MemberDeclarationSyntax RemoveModifier(this MemberDeclarationSyntax memberDeclaration, SyntaxKind kind) 43 | { 44 | int index = memberDeclaration.Modifiers.IndexOf(kind); 45 | 46 | if (index != -1) 47 | { 48 | return memberDeclaration.WithModifiers(memberDeclaration.Modifiers.RemoveAt(index)); 49 | } 50 | 51 | return memberDeclaration; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Extensions/MethodDeclarationSyntaxExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using Microsoft.CodeAnalysis.CSharp.Syntax; 8 | 9 | namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions; 10 | 11 | /// 12 | /// Extension methods for the type. 13 | /// 14 | internal static class MethodDeclarationSyntaxExtensions 15 | { 16 | /// 17 | /// Checks whether a given has or could potentially have any attribute lists. 18 | /// 19 | /// The input to check. 20 | /// Whether has or potentially has any attribute lists. 21 | public static bool HasOrPotentiallyHasAttributeLists(this MethodDeclarationSyntax methodDeclaration) 22 | { 23 | // If the declaration has any attribute lists, there's nothing left to do 24 | if (methodDeclaration.AttributeLists.Count > 0) 25 | { 26 | return true; 27 | } 28 | 29 | // If there are no attributes, check whether the method declaration has the partial keyword. If it 30 | // does, there could potentially be attribute lists on the other partial definition/implementation. 31 | return methodDeclaration.Modifiers.Any(SyntaxKind.PartialKeyword); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Extensions/SourceProductionContextExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Text; 6 | using Microsoft.CodeAnalysis; 7 | using Microsoft.CodeAnalysis.CSharp.Syntax; 8 | 9 | namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions; 10 | 11 | /// 12 | /// Extension methods for the type. 13 | /// 14 | internal static class SourceProductionContextExtensions 15 | { 16 | /// 17 | /// Adds a new source file to a target instance. 18 | /// 19 | /// The input instance to use. 20 | /// The name of the source file to add. 21 | /// The instance representing the syntax tree to add. 22 | public static void AddSource(this SourceProductionContext context, string name, CompilationUnitSyntax compilationUnit) 23 | { 24 | #if !ROSLYN_4_3_1_OR_GREATER 25 | // We're fine with the extra allocation in the few cases where adjusting the filename is necessary. 26 | // This will only ever be done when code generation is executed again anyway, which is a slow path. 27 | name = name.Replace('+', '.').Replace('`', '_'); 28 | #endif 29 | 30 | // Add the UTF8 text for the input compilation unit 31 | context.AddSource(name, compilationUnit.GetText(Encoding.UTF8)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Extensions/SymbolInfoExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics.CodeAnalysis; 6 | using Microsoft.CodeAnalysis; 7 | 8 | namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions; 9 | 10 | /// 11 | /// Extension methods for the type. 12 | /// 13 | internal static class SymbolInfoExtensions 14 | { 15 | /// 16 | /// Tries to get the resolved attribute type symbol from a given value. 17 | /// 18 | /// The value to check. 19 | /// The resulting attribute type symbol, if correctly resolved. 20 | /// Whether is resolved to a symbol. 21 | /// 22 | /// This can be used to ensure users haven't eg. spelled names incorrectly or missed a using directive. Normally, code would just 23 | /// not compile if that was the case, but that doesn't apply for attributes using invalid targets. In that case, Roslyn will ignore 24 | /// any errors, meaning the generator has to validate the type symbols are correctly resolved on its own. 25 | /// 26 | public static bool TryGetAttributeTypeSymbol(this SymbolInfo symbolInfo, [NotNullWhen(true)] out INamedTypeSymbol? typeSymbol) 27 | { 28 | ISymbol? attributeSymbol = symbolInfo.Symbol; 29 | 30 | // If no symbol is selected and there is a single candidate symbol, use that 31 | if (attributeSymbol is null && symbolInfo.CandidateSymbols is [ISymbol candidateSymbol]) 32 | { 33 | attributeSymbol = candidateSymbol; 34 | } 35 | 36 | // Extract the symbol from either the current one or the containing type 37 | if ((attributeSymbol as INamedTypeSymbol ?? attributeSymbol?.ContainingType) is not INamedTypeSymbol resultingSymbol) 38 | { 39 | typeSymbol = null; 40 | 41 | return false; 42 | } 43 | 44 | typeSymbol = resultingSymbol; 45 | 46 | return true; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Extensions/SymbolKindExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using Microsoft.CodeAnalysis; 7 | 8 | namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions; 9 | 10 | /// 11 | /// Extension methods for the type. 12 | /// 13 | internal static class SymbolKindExtensions 14 | { 15 | /// 16 | /// Converts a value to either "field" or "property" based on the kind. 17 | /// 18 | /// The input value. 19 | /// Either "field" or "property" based on . 20 | /// Thrown if is neither nor . 21 | public static string ToFieldOrPropertyKeyword(this SymbolKind kind) 22 | { 23 | return kind switch 24 | { 25 | SymbolKind.Field => "field", 26 | SymbolKind.Property => "property", 27 | _ => throw new ArgumentException($"Unsupported symbol kind '{kind}' for field or property keyword conversion."), 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Extensions/SyntaxTokenExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | 8 | namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions; 9 | 10 | /// 11 | /// Extension methods for the type. 12 | /// 13 | internal static class SyntaxTokenExtensions 14 | { 15 | /// 16 | /// Deconstructs a into its value. 17 | /// 18 | /// The input value. 19 | /// The resulting value for . 20 | public static void Deconstruct(this SyntaxToken syntaxToken, out SyntaxKind syntaxKind) 21 | { 22 | syntaxKind = syntaxToken.Kind(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Extensions/SyntaxTokenListExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | 8 | namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions; 9 | 10 | /// 11 | /// Extension methods for the type. 12 | /// 13 | internal static class SyntaxTokenListExtensions 14 | { 15 | /// 16 | /// Checks whether a given value contains any accessibility modifiers. 17 | /// 18 | /// The input value to check. 19 | /// Whether contains any accessibility modifiers. 20 | public static bool ContainsAnyAccessibilityModifiers(this SyntaxTokenList syntaxList) 21 | { 22 | foreach (SyntaxToken token in syntaxList) 23 | { 24 | if (SyntaxFacts.IsAccessibilityModifier(token.Kind())) 25 | { 26 | return true; 27 | } 28 | } 29 | 30 | return false; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Input/Models/CanExecuteExpressionType.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Mvvm.SourceGenerators.Input.Models; 6 | 7 | /// 8 | /// A type describing the type of expression for the "CanExecute" property of a command. 9 | /// 10 | public enum CanExecuteExpressionType 11 | { 12 | /// 13 | /// A method invocation lambda with discard: _ => Method(). 14 | /// 15 | MethodInvocationLambdaWithDiscard, 16 | 17 | /// 18 | /// A property access lambda: () => Property. 19 | /// 20 | PropertyAccessLambda, 21 | 22 | /// 23 | /// A property access lambda with discard: _ => Property. 24 | /// 25 | PropertyAccessLambdaWithDiscard, 26 | 27 | /// 28 | /// A method group expression: Method. 29 | /// 30 | MethodGroup 31 | } 32 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Messaging/Models/RecipientInfo.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Mvvm.SourceGenerators.Helpers; 6 | 7 | namespace CommunityToolkit.Mvvm.SourceGenerators.Messaging.Models; 8 | 9 | /// 10 | /// A model with gathered info on all message types being handled by a recipient. 11 | /// 12 | /// The filename hint for the current type. 13 | /// The fully qualified type name of the target type. 14 | /// The name of messages being received. 15 | internal sealed record RecipientInfo(string FilenameHint, string TypeName, EquatableArray MessageTypes); 16 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Models/HierarchyInfo.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | // This file is ported and adapted from ComputeSharp (Sergio0694/ComputeSharp), 6 | // more info in ThirdPartyNotices.txt in the root of the project. 7 | 8 | using CommunityToolkit.Mvvm.SourceGenerators.Extensions; 9 | using CommunityToolkit.Mvvm.SourceGenerators.Helpers; 10 | using Microsoft.CodeAnalysis; 11 | using static Microsoft.CodeAnalysis.SymbolDisplayTypeQualificationStyle; 12 | 13 | namespace CommunityToolkit.Mvvm.SourceGenerators.Models; 14 | 15 | /// 16 | /// A model describing the hierarchy info for a specific type. 17 | /// 18 | /// The filename hint for the current type. 19 | /// The metadata name for the current type. 20 | /// Gets the namespace for the current type. 21 | /// Gets the sequence of type definitions containing the current type. 22 | internal sealed partial record HierarchyInfo(string FilenameHint, string MetadataName, string Namespace, EquatableArray Hierarchy) 23 | { 24 | /// 25 | /// Creates a new instance from a given . 26 | /// 27 | /// The input instance to gather info for. 28 | /// A instance describing . 29 | public static HierarchyInfo From(INamedTypeSymbol typeSymbol) 30 | { 31 | using ImmutableArrayBuilder hierarchy = ImmutableArrayBuilder.Rent(); 32 | 33 | for (INamedTypeSymbol? parent = typeSymbol; 34 | parent is not null; 35 | parent = parent.ContainingType) 36 | { 37 | hierarchy.Add(new TypeInfo( 38 | parent.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), 39 | parent.TypeKind, 40 | parent.IsRecord)); 41 | } 42 | 43 | return new( 44 | typeSymbol.GetFullyQualifiedMetadataName(), 45 | typeSymbol.MetadataName, 46 | typeSymbol.ContainingNamespace.ToDisplayString(new(typeQualificationStyle: NameAndContainingTypesAndNamespaces)), 47 | hierarchy.ToImmutable()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Models/Result.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | // This file is ported and adapted from ComputeSharp (Sergio0694/ComputeSharp), 6 | // more info in ThirdPartyNotices.txt in the root of the project. 7 | 8 | using System; 9 | using CommunityToolkit.Mvvm.SourceGenerators.Helpers; 10 | 11 | namespace CommunityToolkit.Mvvm.SourceGenerators.Models; 12 | 13 | /// 14 | /// A model representing a value and an associated set of diagnostic errors. 15 | /// 16 | /// The type of the wrapped value. 17 | /// The wrapped value for the current result. 18 | /// The associated diagnostic errors, if any. 19 | internal sealed record Result(TValue Value, EquatableArray Errors) 20 | where TValue : IEquatable?; 21 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm.SourceGenerators/Models/TypeInfo.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using Microsoft.CodeAnalysis.CSharp.Syntax; 8 | using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; 9 | 10 | namespace CommunityToolkit.Mvvm.SourceGenerators.Models; 11 | 12 | /// 13 | /// A model describing a type info in a type hierarchy. 14 | /// 15 | /// The qualified name for the type. 16 | /// The type of the type in the hierarchy. 17 | /// Whether the type is a record type. 18 | internal sealed record TypeInfo(string QualifiedName, TypeKind Kind, bool IsRecord) 19 | { 20 | /// 21 | /// Creates a instance for the current info. 22 | /// 23 | /// A instance for the current info. 24 | public TypeDeclarationSyntax GetSyntax() 25 | { 26 | // Create the partial type declaration with the kind. 27 | // This code produces a class declaration as follows: 28 | // 29 | // 30 | // { 31 | // } 32 | // 33 | // Note that specifically for record declarations, we also need to explicitly add the open 34 | // and close brace tokens, otherwise member declarations will not be formatted correctly. 35 | return Kind switch 36 | { 37 | TypeKind.Struct => StructDeclaration(QualifiedName), 38 | TypeKind.Interface => InterfaceDeclaration(QualifiedName), 39 | TypeKind.Class when IsRecord => 40 | RecordDeclaration(Token(SyntaxKind.RecordKeyword), QualifiedName) 41 | .WithOpenBraceToken(Token(SyntaxKind.OpenBraceToken)) 42 | .WithCloseBraceToken(Token(SyntaxKind.CloseBraceToken)), 43 | _ => ClassDeclaration(QualifiedName) 44 | }; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Collections/IReadOnlyObservableGroup.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections; 6 | using System.Collections.Specialized; 7 | using System.ComponentModel; 8 | 9 | namespace CommunityToolkit.Mvvm.Collections; 10 | 11 | /// 12 | /// An interface for a grouped collection of items. 13 | /// 14 | public interface IReadOnlyObservableGroup : INotifyPropertyChanged, INotifyCollectionChanged, IEnumerable 15 | { 16 | /// 17 | /// Gets the key for the current collection. 18 | /// 19 | object Key { get; } 20 | 21 | /// 22 | /// Gets the number of items currently in the grouped collection. 23 | /// 24 | int Count { get; } 25 | 26 | /// 27 | /// Gets the element at the specified index in the current collection. 28 | /// 29 | /// The zero-based index of the element to get. 30 | /// The element at the specified index in the read-only list. 31 | /// Thrown if the index is out of range. 32 | object? this[int index] { get; } 33 | } 34 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Collections/IReadOnlyObservableGroup{TKey,TElement}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | namespace CommunityToolkit.Mvvm.Collections; 9 | 10 | /// 11 | /// An interface for a grouped collection of items. 12 | /// 13 | /// The type of the group key. 14 | /// The type of elements in the group. 15 | public interface IReadOnlyObservableGroup : IReadOnlyObservableGroup, IReadOnlyList, IGrouping 16 | where TKey : notnull 17 | { 18 | /// 19 | /// Gets the element at the specified index in the current collection. 20 | /// 21 | /// The zero-based index of the element to get. 22 | /// The element at the specified index in the read-only list. 23 | /// Thrown if the index is out of range. 24 | new TElement this[int index] { get; } 25 | } 26 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Collections/IReadOnlyObservableGroup{TKey}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Mvvm.Collections; 6 | 7 | /// 8 | /// An interface for a grouped collection of items. 9 | /// 10 | /// The type of the group key. 11 | public interface IReadOnlyObservableGroup : IReadOnlyObservableGroup 12 | where TKey : notnull 13 | { 14 | /// 15 | /// Gets the key for the current collection. 16 | /// 17 | new TKey Key { get; } 18 | } 19 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Collections/Internals/ObservableGroupHelper.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.ComponentModel; 6 | 7 | namespace CommunityToolkit.Mvvm.Collections.Internals; 8 | 9 | /// 10 | /// A helper type for the type. 11 | /// 12 | internal static class ObservableGroupHelper 13 | { 14 | /// 15 | /// The cached for 16 | /// 17 | public static readonly PropertyChangedEventArgs KeyChangedEventArgs = new(nameof(IReadOnlyObservableGroup.Key)); 18 | } -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Collections/ReadOnlyObservableGroup{TKey,TElement}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.ObjectModel; 6 | using System.Diagnostics; 7 | 8 | namespace CommunityToolkit.Mvvm.Collections; 9 | 10 | /// 11 | /// A read-only observable group. It associates a to a . 12 | /// 13 | /// The type of the group key. 14 | /// The type of elements in the group. 15 | [DebuggerDisplay("Key = {Key}, Count = {Count}")] 16 | public sealed class ReadOnlyObservableGroup : ReadOnlyObservableCollection, IReadOnlyObservableGroup 17 | where TKey : notnull 18 | { 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// 22 | /// The key of the group. 23 | /// The collection of items to add in the group. 24 | /// Thrown if or are . 25 | public ReadOnlyObservableGroup(TKey key, ObservableCollection collection) 26 | : base(collection) 27 | { 28 | ArgumentNullException.For.ThrowIfNull(key); 29 | 30 | Key = key; 31 | } 32 | 33 | /// 34 | /// Initializes a new instance of the class. 35 | /// 36 | /// The to wrap. 37 | /// Thrown if is . 38 | public ReadOnlyObservableGroup(ObservableGroup group) 39 | : base(group) 40 | { 41 | Key = group.Key; 42 | } 43 | 44 | /// 45 | public TKey Key { get; } 46 | 47 | /// 48 | object IReadOnlyObservableGroup.Key => Key; 49 | 50 | /// 51 | object? IReadOnlyObservableGroup.this[int index] => this[index]; 52 | } 53 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.FeatureSwitches.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.Windows.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <_MvvmToolkitIsUsingWindowsRuntimePack>false 6 | <_MvvmToolkitIsUsingWindowsRuntimePack Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0-windows10.0.17763.0'))">true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/CommunityToolkit.Mvvm.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <_CommunityToolkitMvvmFeatureSwitchesTargets>$(MSBuildThisFileDirectory)CommunityToolkit.Mvvm.FeatureSwitches.targets 6 | <_CommunityToolkitMvvmSourceGeneratorsTargets>$(MSBuildThisFileDirectory)CommunityToolkit.Mvvm.SourceGenerators.targets 7 | <_CommunityToolkitMvvmWindowsTargets>$(MSBuildThisFileDirectory)CommunityToolkit.Mvvm.Windows.targets 8 | <_CommunityToolkitMvvmWindowsSdkTargets>$(MSBuildThisFileDirectory)CommunityToolkit.Mvvm.WindowsSdk.targets 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/ComponentModel/Attributes/INotifyPropertyChangedAttribute.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.ComponentModel; 7 | 8 | namespace CommunityToolkit.Mvvm.ComponentModel; 9 | 10 | /// 11 | /// An attribute that indicates that a given type should implement the interface and 12 | /// have minimal built-in functionality to support it. This includes exposing the necessary event and having two methods 13 | /// to raise it that mirror and 14 | /// . For more extensive support, use . 15 | /// 16 | /// This attribute can be used as follows: 17 | /// 18 | /// [INotifyPropertyChanged] 19 | /// partial class MyViewModel : SomeOtherClass 20 | /// { 21 | /// // Other members here... 22 | /// } 23 | /// 24 | /// 25 | /// 26 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 27 | public sealed class INotifyPropertyChangedAttribute : Attribute 28 | { 29 | /// 30 | /// Gets or sets a value indicating whether or not to also generate all the additional helper methods that are found 31 | /// in as well (eg. ). 32 | /// If set to , only the event and 33 | /// the two overloads will be generated. 34 | /// The default value is . 35 | /// 36 | public bool IncludeAdditionalHelperMethods { get; init; } = true; 37 | } 38 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/ComponentModel/Attributes/NotifyDataErrorInfoAttribute.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace CommunityToolkit.Mvvm.ComponentModel; 8 | 9 | /// 10 | /// An attribute that can be used to support in generated properties, when applied to 11 | /// partial properties contained in a type that is inheriting from and using any validation attributes. 12 | /// When this attribute is used, the generated property setter will also call . 13 | /// This allows generated properties to opt-in into validation behavior without having to fallback into a full explicit observable property. 14 | /// 15 | /// This attribute can be used as follows: 16 | /// 17 | /// partial class MyViewModel : ObservableValidator 18 | /// { 19 | /// [ObservableProperty] 20 | /// [NotifyDataErrorInfo] 21 | /// [Required] 22 | /// [MinLength(2)] 23 | /// public partial string Username { get; set; } 24 | /// } 25 | /// 26 | /// 27 | /// And with this, code analogous to this will be generated: 28 | /// 29 | /// partial class MyViewModel 30 | /// { 31 | /// public partial string Username 32 | /// { 33 | /// get => field; 34 | /// set => SetProperty(ref field, value, validate: true); 35 | /// } 36 | /// } 37 | /// 38 | /// 39 | /// 40 | /// 41 | /// This attribute can also be used on a class, which will enable the validation on all generated properties contained in it. 42 | /// 43 | /// 44 | /// Just like , this attribute can also be used on fields as well. 45 | /// 46 | /// 47 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 48 | public sealed class NotifyDataErrorInfoAttribute : Attribute 49 | { 50 | } 51 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/ComponentModel/Attributes/NotifyPropertyChangedRecipientsAttribute.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | 7 | namespace CommunityToolkit.Mvvm.ComponentModel; 8 | 9 | /// 10 | /// An attribute that can be used to support in generated properties, when applied to fields and properties 11 | /// contained in a type that is either inheriting from , or annotated with . 12 | /// When this attribute is used, the generated property setter will also call . 13 | /// This allows generated properties to opt-in into broadcasting behavior without having to fallback into a full explicit observable property. 14 | /// 15 | /// This attribute can be used as follows: 16 | /// 17 | /// partial class MyViewModel : ObservableRecipient 18 | /// { 19 | /// [ObservableProperty] 20 | /// [NotifyPropertyChangedRecipients] 21 | /// public partial string Username; 22 | /// } 23 | /// 24 | /// 25 | /// 26 | /// And with this, code analogous to this will be generated: 27 | /// 28 | /// partial class MyViewModel 29 | /// { 30 | /// public partial string Username 31 | /// { 32 | /// get => field; 33 | /// set => SetProperty(ref field, value, broadcast: true); 34 | /// } 35 | /// } 36 | /// 37 | /// 38 | /// 39 | /// This attribute can also be added to a class, and if so it will affect all generated properties in that type and inherited types. 40 | /// 41 | /// 42 | /// 43 | /// Just like , this attribute can also be used on fields as well. 44 | /// 45 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 46 | public sealed class NotifyPropertyChangedRecipientsAttribute : Attribute 47 | { 48 | } 49 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/ComponentModel/Attributes/ObservableObjectAttribute.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.ComponentModel; 7 | 8 | namespace CommunityToolkit.Mvvm.ComponentModel; 9 | 10 | /// 11 | /// An attribute that indicates that a given type should have all the members from 12 | /// generated into it, as well as the and 13 | /// interfaces. This can be useful when you want the same functionality from into a class 14 | /// that already inherits from another one (since C# doesn't support multiple inheritance). This attribute will trigger 15 | /// the source generator to just create the same APIs directly into the decorated class. 16 | /// 17 | /// This attribute can be used as follows: 18 | /// 19 | /// [ObservableObject] 20 | /// partial class MyViewModel : SomeOtherClass 21 | /// { 22 | /// // Other members here... 23 | /// } 24 | /// 25 | /// 26 | /// And with this, the same APIs from will be available on this type as well. 27 | /// 28 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 29 | public sealed class ObservableObjectAttribute : Attribute 30 | { 31 | } 32 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/ComponentModel/__Internals/__ObservableValidatorHelper.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.ComponentModel; 7 | using System.Diagnostics.CodeAnalysis; 8 | 9 | namespace CommunityToolkit.Mvvm.ComponentModel.__Internals; 10 | 11 | /// 12 | /// An internal helper to support the source generator APIs related to . 13 | /// This type is not intended to be used directly by user code. 14 | /// 15 | [EditorBrowsable(EditorBrowsableState.Never)] 16 | [Obsolete("This type is not intended to be used directly by user code")] 17 | public static class __ObservableValidatorHelper 18 | { 19 | /// 20 | /// Invokes externally on a target instance. 21 | /// 22 | /// The target instance. 23 | /// The value to test for the specified property. 24 | /// The name of the property to validate. 25 | [EditorBrowsable(EditorBrowsableState.Never)] 26 | [Obsolete("This method is not intended to be called directly by user code")] 27 | [UnconditionalSuppressMessage( 28 | "ReflectionAnalysis", 29 | "IL2026:RequiresUnreferencedCode", 30 | Justification = "This helper is called by generated code from public APIs that have the proper annotations already (and we don't want generated code to produce warnings that developers cannot fix).")] 31 | public static void ValidateProperty(ObservableValidator instance, object? value, string propertyName) 32 | { 33 | instance.ValidateProperty(value, propertyName); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Input/IAsyncRelayCommandExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Windows.Input; 6 | using CommunityToolkit.Mvvm.Input.Internals; 7 | 8 | namespace CommunityToolkit.Mvvm.Input; 9 | 10 | /// 11 | /// Extensions for the type. 12 | /// 13 | public static class IAsyncRelayCommandExtensions 14 | { 15 | /// 16 | /// Creates an instance that can be used to cancel execution on the input command. 17 | /// The returned command will also notify when it can be executed based on the state of the wrapped command. 18 | /// 19 | /// The input instance to create a cancellation command for. 20 | /// An instance that can be used to monitor and signal cancellation for . 21 | /// The returned instance is not guaranteed to be unique across multiple invocations with the same arguments. 22 | /// Thrown if is . 23 | public static ICommand CreateCancelCommand(this IAsyncRelayCommand command) 24 | { 25 | ArgumentNullException.ThrowIfNull(command); 26 | 27 | // If the command is known not to ever allow cancellation, just reuse the same instance 28 | if (command is ICancellationAwareCommand { IsCancellationSupported: false }) 29 | { 30 | return DisabledCommand.Instance; 31 | } 32 | 33 | // Create a new cancel command wrapping the input one 34 | return new CancelCommand(command); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Input/Interfaces/IAsyncRelayCommand{T}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading.Tasks; 6 | 7 | namespace CommunityToolkit.Mvvm.Input; 8 | 9 | /// 10 | /// A generic interface representing a more specific version of . 11 | /// 12 | /// The type used as argument for the interface methods. 13 | /// This interface is needed to solve the diamond problem with base classes. 14 | public interface IAsyncRelayCommand : IAsyncRelayCommand, IRelayCommand 15 | { 16 | /// 17 | /// Provides a strongly-typed variant of . 18 | /// 19 | /// The input parameter. 20 | /// The representing the async operation being executed. 21 | Task ExecuteAsync(T? parameter); 22 | } 23 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Input/Interfaces/IRelayCommand.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Windows.Input; 6 | 7 | namespace CommunityToolkit.Mvvm.Input; 8 | 9 | /// 10 | /// An interface expanding with the ability to raise 11 | /// the event externally. 12 | /// 13 | public interface IRelayCommand : ICommand 14 | { 15 | /// 16 | /// Notifies that the property has changed. 17 | /// 18 | void NotifyCanExecuteChanged(); 19 | } 20 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Input/Interfaces/IRelayCommand{T}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Windows.Input; 6 | 7 | namespace CommunityToolkit.Mvvm.Input; 8 | 9 | /// 10 | /// A generic interface representing a more specific version of . 11 | /// 12 | /// The type used as argument for the interface methods. 13 | public interface IRelayCommand : IRelayCommand 14 | { 15 | /// 16 | /// Provides a strongly-typed variant of . 17 | /// 18 | /// The input parameter. 19 | /// Whether or not the current command can be executed. 20 | /// Use this overload to avoid boxing, if is a value type. 21 | bool CanExecute(T? parameter); 22 | 23 | /// 24 | /// Provides a strongly-typed variant of . 25 | /// 26 | /// The input parameter. 27 | /// Use this overload to avoid boxing, if is a value type. 28 | void Execute(T? parameter); 29 | } 30 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Input/Internals/CancelCommand.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.ComponentModel; 7 | using System.Windows.Input; 8 | 9 | namespace CommunityToolkit.Mvvm.Input.Internals; 10 | 11 | /// 12 | /// A implementation wrapping to support cancellation. 13 | /// 14 | internal sealed partial class CancelCommand : ICommand 15 | { 16 | /// 17 | /// The wrapped instance. 18 | /// 19 | private readonly IAsyncRelayCommand command; 20 | 21 | /// 22 | /// Creates a new instance. 23 | /// 24 | /// The instance to wrap. 25 | public CancelCommand(IAsyncRelayCommand command) 26 | { 27 | this.command = command; 28 | 29 | this.command.PropertyChanged += OnPropertyChanged; 30 | } 31 | 32 | /// 33 | public event EventHandler? CanExecuteChanged; 34 | 35 | /// 36 | public bool CanExecute(object? parameter) 37 | { 38 | return this.command.CanBeCanceled; 39 | } 40 | 41 | /// 42 | public void Execute(object? parameter) 43 | { 44 | this.command.Cancel(); 45 | } 46 | 47 | /// 48 | private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e) 49 | { 50 | if (e.PropertyName is null or nameof(IAsyncRelayCommand.CanBeCanceled)) 51 | { 52 | CanExecuteChanged?.Invoke(this, EventArgs.Empty); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Input/Internals/DisabledCommand.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Windows.Input; 7 | 8 | namespace CommunityToolkit.Mvvm.Input.Internals; 9 | 10 | /// 11 | /// A reusable instance that is always disabled. 12 | /// 13 | internal sealed partial class DisabledCommand : ICommand 14 | { 15 | /// 16 | public event EventHandler? CanExecuteChanged 17 | { 18 | add { } 19 | remove { } 20 | } 21 | 22 | /// 23 | /// Gets a shared, reusable instance. 24 | /// 25 | /// 26 | /// This instance can safely be used across multiple objects without having 27 | /// to worry about this static keeping others alive, as the event uses a 28 | /// custom accessor that just discards items (as the event is known to never 29 | /// be raised). As such, this instance will never act as root for other objects. 30 | /// 31 | public static DisabledCommand Instance { get; } = new(); 32 | 33 | /// 34 | public bool CanExecute(object? parameter) 35 | { 36 | return false; 37 | } 38 | 39 | /// 40 | public void Execute(object? parameter) 41 | { 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Input/Internals/ICancellationAwareCommand.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Mvvm.Input.Internals; 6 | 7 | /// 8 | /// An interface for commands that know whether they support cancellation or not. 9 | /// 10 | internal interface ICancellationAwareCommand 11 | { 12 | /// 13 | /// Gets whether or not the current command supports cancellation. 14 | /// 15 | bool IsCancellationSupported { get; } 16 | } 17 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Messaging/IRecipient{TMessage}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Mvvm.Messaging; 6 | 7 | /// 8 | /// An interface for a recipient that declares a registration for a specific message type. 9 | /// 10 | /// The type of message to receive. 11 | public interface IRecipient 12 | where TMessage : class 13 | { 14 | /// 15 | /// Receives a given message instance. 16 | /// 17 | /// The message being received. 18 | void Receive(TMessage message); 19 | } 20 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Messaging/Internals/System/Collections.Generic/IDictionary2.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Collections.Generic; 6 | 7 | /// 8 | /// A base interface masking instances and exposing non-generic functionalities. 9 | /// 10 | internal interface IDictionary2 11 | { 12 | /// 13 | /// Gets the count of entries in the dictionary. 14 | /// 15 | int Count { get; } 16 | 17 | /// 18 | /// Clears the current dictionary. 19 | /// 20 | void Clear(); 21 | } 22 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Messaging/Internals/System/Collections.Generic/IDictionary2{TKey,TValue}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Collections.Generic; 6 | 7 | /// 8 | /// An interface providing key type contravariant and value type covariant access 9 | /// to a instance. 10 | /// 11 | /// The contravariant type of keys in the dictionary. 12 | /// The covariant type of values in the dictionary. 13 | internal interface IDictionary2 : IDictionary2 14 | where TKey : IEquatable 15 | where TValue : class? 16 | { 17 | /// 18 | /// Gets the value with the specified key. 19 | /// 20 | /// The key to look for. 21 | /// The returned value. 22 | /// Thrown if the key wasn't present. 23 | TValue this[TKey key] { get; } 24 | } 25 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Messaging/Internals/System/Collections.Generic/IDictionary2{TKey}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace System.Collections.Generic; 6 | 7 | /// 8 | /// An interface providing key type contravariant access to a instance. 9 | /// 10 | /// The contravariant type of keys in the dictionary. 11 | internal interface IDictionary2 : IDictionary2 12 | where TKey : IEquatable 13 | { 14 | /// 15 | /// Tries to remove a value with a specified key, if present. 16 | /// 17 | /// The key of the value to remove. 18 | /// Whether or not the key was present. 19 | bool TryRemove(TKey key); 20 | } 21 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Messaging/Internals/System/Runtime.CompilerServices/ConditionalWeakTableExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | #if !NET6_0_OR_GREATER 6 | 7 | namespace System.Runtime.CompilerServices; 8 | 9 | /// 10 | /// Helper methods for the type. 11 | /// 12 | internal static class ConditionalWeakTableExtensions 13 | { 14 | /// 15 | /// Tries to add a new pair to the table. 16 | /// 17 | /// Tke key of items to store in the table. 18 | /// The values to store in the table. 19 | /// The input instance to modify. 20 | /// The key to add. 21 | /// The value to associate with key. 22 | public static bool TryAdd(this ConditionalWeakTable table, TKey key, TValue value) 23 | where TKey : class 24 | where TValue : class? 25 | { 26 | // There is no way to do this on .NET Standard 2.0 or 2.1 without exception handling 27 | try 28 | { 29 | table.Add(key, value); 30 | 31 | return true; 32 | } 33 | catch (ArgumentException) 34 | { 35 | return false; 36 | } 37 | } 38 | } 39 | 40 | #endif -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Messaging/Internals/Unit.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Runtime.CompilerServices; 7 | 8 | namespace CommunityToolkit.Mvvm.Messaging.Internals; 9 | 10 | /// 11 | /// An empty type representing a generic token with no specific value. 12 | /// 13 | internal readonly struct Unit : IEquatable 14 | { 15 | /// 16 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 17 | public bool Equals(Unit other) 18 | { 19 | return true; 20 | } 21 | 22 | /// 23 | public override bool Equals(object? obj) 24 | { 25 | return obj is Unit; 26 | } 27 | 28 | /// 29 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 30 | public override int GetHashCode() 31 | { 32 | return 0; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Messaging/MessageHandler{TRecipient,TMessage}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Mvvm.Messaging; 6 | 7 | /// 8 | /// A used to represent actions to invoke when a message is received. 9 | /// The recipient is given as an input argument to allow message registrations to avoid creating 10 | /// closures: if an instance method on a recipient needs to be invoked it is possible to just 11 | /// cast the recipient to the right type and then access the local method from that instance. 12 | /// 13 | /// The type of recipient for the message. 14 | /// The type of message to receive. 15 | /// The recipient that is receiving the message. 16 | /// The message being received. 17 | public delegate void MessageHandler(TRecipient recipient, TMessage message) 18 | where TRecipient : class 19 | where TMessage : class; 20 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Messaging/Messages/CollectionRequestMessage{T}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | using System.ComponentModel; 8 | using System.Runtime.CompilerServices; 9 | 10 | namespace CommunityToolkit.Mvvm.Messaging.Messages; 11 | 12 | /// 13 | /// A for request messages that can receive multiple replies, which can either be used directly or through derived classes. 14 | /// 15 | /// The type of request to make. 16 | public class CollectionRequestMessage : IEnumerable 17 | { 18 | private readonly List responses = new(); 19 | 20 | /// 21 | /// Gets the message responses. 22 | /// 23 | public IReadOnlyCollection Responses => this.responses; 24 | 25 | /// 26 | /// Replies to the current request message. 27 | /// 28 | /// The response to use to reply to the request message. 29 | public void Reply(T response) 30 | { 31 | this.responses.Add(response); 32 | } 33 | 34 | /// 35 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 36 | [EditorBrowsable(EditorBrowsableState.Never)] 37 | public IEnumerator GetEnumerator() 38 | { 39 | return this.responses.GetEnumerator(); 40 | } 41 | 42 | /// 43 | IEnumerator IEnumerable.GetEnumerator() 44 | { 45 | return this.GetEnumerator(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Messaging/Messages/PropertyChangedMessage{T}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | // This file is inspired from the MvvmLight library (lbugnion/MvvmLight), 6 | // more info in ThirdPartyNotices.txt in the root of the project. 7 | 8 | namespace CommunityToolkit.Mvvm.Messaging.Messages; 9 | 10 | /// 11 | /// A message used to broadcast property changes in observable objects. 12 | /// 13 | /// The type of the property to broadcast the change for. 14 | public class PropertyChangedMessage 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | /// The original sender of the broadcast message. 20 | /// The name of the property that changed. 21 | /// The value that the property had before the change. 22 | /// The value that the property has after the change. 23 | /// Thrown if is . 24 | public PropertyChangedMessage(object sender, string? propertyName, T oldValue, T newValue) 25 | { 26 | ArgumentNullException.ThrowIfNull(sender); 27 | 28 | Sender = sender; 29 | PropertyName = propertyName; 30 | OldValue = oldValue; 31 | NewValue = newValue; 32 | } 33 | 34 | /// 35 | /// Gets the original sender of the broadcast message. 36 | /// 37 | public object Sender { get; } 38 | 39 | /// 40 | /// Gets the name of the property that changed. 41 | /// 42 | public string? PropertyName { get; } 43 | 44 | /// 45 | /// Gets the value that the property had before the change. 46 | /// 47 | public T OldValue { get; } 48 | 49 | /// 50 | /// Gets the value that the property has after the change. 51 | /// 52 | public T NewValue { get; } 53 | } 54 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Messaging/Messages/ValueChangedMessage{T}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace CommunityToolkit.Mvvm.Messaging.Messages; 6 | 7 | /// 8 | /// A base message that signals whenever a specific value has changed. 9 | /// 10 | /// The type of value that has changed. 11 | public class ValueChangedMessage 12 | { 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | /// The value that has changed. 17 | public ValueChangedMessage(T value) 18 | { 19 | Value = value; 20 | } 21 | 22 | /// 23 | /// Gets the value that has changed. 24 | /// 25 | public T Value { get; } 26 | } 27 | -------------------------------------------------------------------------------- /src/CommunityToolkit.Mvvm/Properties/ILLink.Substitutions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | all 8 | build; analyzers 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Common.UnitTests/CommunityToolkit.Common.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;net7.0;net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Common.UnitTests/Extensions/Test_ArrayExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Diagnostics; 7 | using System.Linq; 8 | using Microsoft.VisualStudio.TestTools.UnitTesting; 9 | 10 | namespace CommunityToolkit.Common.UnitTests.Extensions; 11 | 12 | [TestClass] 13 | public class Test_ArrayExtensions 14 | { 15 | [TestMethod] 16 | public void Test_ArrayExtensions_Jagged_GetColumn() 17 | { 18 | int[][] array = 19 | { 20 | new int[] { 5, 2, 4 }, 21 | new int[] { 6, 3 }, 22 | new int[] { 7 } 23 | }; 24 | 25 | int[]? col = array.GetColumn(1).ToArray(); 26 | 27 | CollectionAssert.AreEquivalent(new int[] { 2, 3, 0 }, col); 28 | } 29 | 30 | [TestMethod] 31 | public void Test_ArrayExtensions_Jagged_GetColumn_Exception() 32 | { 33 | int[][] array = 34 | { 35 | new int[] { 5, 2, 4 }, 36 | new int[] { 6, 3 }, 37 | new int[] { 7 } 38 | }; 39 | 40 | _ = Assert.ThrowsException(() => 41 | { 42 | _ = array.GetColumn(-1).ToArray(); 43 | }); 44 | 45 | _ = Assert.ThrowsException(() => 46 | { 47 | _ = array.GetColumn(3).ToArray(); 48 | }); 49 | } 50 | 51 | [TestMethod] 52 | public void Test_ArrayExtensions_Rectangular_ToString() 53 | { 54 | int[,] array = 55 | { 56 | { 5, 2, 4 }, 57 | { 6, 3, -1 }, 58 | { 7, 0, 9 } 59 | }; 60 | 61 | string value = array.ToArrayString(); 62 | 63 | Debug.WriteLine(value); 64 | 65 | Assert.AreEqual("[[5,\t2,\t4]," + Environment.NewLine + " [6,\t3,\t-1]," + Environment.NewLine + " [7,\t0,\t9]]", value); 66 | } 67 | 68 | [TestMethod] 69 | public void Test_ArrayExtensions_Jagged_ToString() 70 | { 71 | int[][] array = 72 | { 73 | new int[] { 5, 2 }, 74 | new int[] { 6, 3, -1, 2 }, 75 | new int[] { 7, 0, 9 } 76 | }; 77 | 78 | string value = array.ToArrayString(); 79 | 80 | Debug.WriteLine(value); 81 | 82 | Assert.AreEqual("[[5,\t2]," + Environment.NewLine + " [6,\t3,\t-1,\t2]," + Environment.NewLine + " [7,\t0,\t9]]", value); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Common.UnitTests/Test_Converters.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | namespace CommunityToolkit.Common.UnitTests; 8 | 9 | [TestClass] 10 | public class Test_Converters 11 | { 12 | [TestMethod] 13 | [DataRow(1024L - 1, "1023 bytes")] 14 | [DataRow(1024L, "1.0 KB")] 15 | [DataRow(1024L * 1024, "1.0 MB")] 16 | [DataRow(1024L * 1024 * 1024, "1.0 GB")] 17 | [DataRow(1024L * 1024 * 1024 * 1024, "1.0 TB")] 18 | [DataRow(1024L * 1024 * 1024 * 1024 * 1024, "1.0 PB")] 19 | [DataRow(1024L * 1024 * 1024 * 1024 * 1024 * 1024, "1.0 EB")] 20 | public void Test_ToFileSizeString(long size, string expected) 21 | { 22 | Assert.AreEqual(expected, Converters.ToFileSizeString(size)); 23 | } 24 | } -------------------------------------------------------------------------------- /tests/CommunityToolkit.Diagnostics.UnitTests/CommunityToolkit.Diagnostics.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;net7.0;net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Diagnostics.UnitTests/Extensions/Test_ValueTypeExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | namespace CommunityToolkit.Diagnostics.UnitTests.Extensions; 8 | 9 | [TestClass] 10 | public class Test_ValueTypeExtensions 11 | { 12 | [TestMethod] 13 | public void Test_ValueTypeExtensions_ToHexString() 14 | { 15 | Assert.AreEqual(((byte)0).ToHexString(), "0x00"); 16 | Assert.AreEqual(((byte)127).ToHexString(), "0x7F"); 17 | Assert.AreEqual(((byte)255).ToHexString(), "0xFF"); 18 | Assert.AreEqual(((ushort)6458).ToHexString(), "0x193A"); 19 | Assert.AreEqual(6458.ToHexString(), "0x0000193A"); 20 | Assert.AreEqual((-1).ToHexString(), "0xFFFFFFFF"); 21 | Assert.AreEqual(true.ToHexString(), "0x01"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Buffers/Internals/TrackingArrayPool{T}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Buffers; 6 | using System.Collections.Generic; 7 | 8 | namespace CommunityToolkit.HighPerformance.UnitTests.Buffers.Internals; 9 | 10 | internal sealed class TrackingArrayPool : ArrayPool 11 | { 12 | private readonly ArrayPool pool = Create(); 13 | 14 | private readonly HashSet arrays = new(); 15 | 16 | /// 17 | /// Gets the collection of currently rented out arrays 18 | /// 19 | public IReadOnlyCollection RentedArrays => this.arrays; 20 | 21 | /// 22 | public override T[] Rent(int minimumLength) 23 | { 24 | T[] array = this.pool.Rent(minimumLength); 25 | 26 | _ = this.arrays.Add(array); 27 | 28 | return array; 29 | } 30 | 31 | /// 32 | public override void Return(T[] array, bool clearArray = false) 33 | { 34 | _ = this.arrays.Remove(array); 35 | 36 | this.pool.Return(array, clearArray); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Buffers/Internals/UnmanagedSpanOwner.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Buffers; 7 | using System.Runtime.InteropServices; 8 | 9 | namespace CommunityToolkit.HighPerformance.UnitTests.Buffers.Internals; 10 | 11 | /// 12 | /// An owner for a buffer of an unmanaged type, recycling arrays to save memory. 13 | /// 14 | /// The type of items to store in the rented buffers. 15 | internal sealed unsafe class UnmanagedSpanOwner : MemoryManager 16 | where T : unmanaged 17 | { 18 | /// 19 | /// The size of the current instance 20 | /// 21 | private readonly int length; 22 | 23 | /// 24 | /// The pointer to the underlying array. 25 | /// 26 | private IntPtr ptr; 27 | 28 | /// 29 | /// Initializes a new instance of the class. 30 | /// 31 | /// The size of the buffer to rent. 32 | public UnmanagedSpanOwner(int size) 33 | { 34 | this.ptr = Marshal.AllocHGlobal(size * sizeof(T)); 35 | this.length = size; 36 | } 37 | 38 | /// 39 | /// Gets the length of the buffer in use. 40 | /// 41 | public int Length => this.length; 42 | 43 | /// 44 | /// Gets a pointer to the start of the buffer in use. 45 | /// 46 | public T* Ptr => (T*)this.ptr; 47 | 48 | /// 49 | protected override void Dispose(bool disposing) 50 | { 51 | IntPtr ptr = this.ptr; 52 | 53 | if (ptr == IntPtr.Zero) 54 | { 55 | return; 56 | } 57 | 58 | this.ptr = IntPtr.Zero; 59 | 60 | Marshal.FreeHGlobal(ptr); 61 | } 62 | 63 | /// 64 | public override Span GetSpan() 65 | { 66 | return new((void*)this.ptr, this.length); 67 | } 68 | 69 | /// 70 | public override MemoryHandle Pin(int elementIndex = 0) 71 | { 72 | throw new NotImplementedException(); 73 | } 74 | 75 | /// 76 | public override void Unpin() 77 | { 78 | throw new NotImplementedException(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/CommunityToolkit.HighPerformance.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;net7.0;net8.0 5 | true 6 | $(NoWarn);CA2252 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_ArrayExtensions.1D.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics.CodeAnalysis; 6 | using System.Runtime.CompilerServices; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | 9 | namespace CommunityToolkit.HighPerformance.UnitTests.Extensions; 10 | 11 | [TestClass] 12 | [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1601", Justification = "Partial test class")] 13 | public partial class Test_ArrayExtensions 14 | { 15 | [TestMethod] 16 | public void Test_ArrayExtensions_DangerousGetReference() 17 | { 18 | string[] tokens = "aa,bb,cc,dd,ee,ff,gg,hh,ii".Split(','); 19 | 20 | // In all these "DangerousGetReference" tests, we need to ensure that a reference to a given 21 | // item within an array is effectively the one corresponding to the one whe expect, which is 22 | // either a reference to the first item if we use "DangerousGetReference", or one to the n-th 23 | // item if we use "DangerousGetReferenceAt". So all these tests just invoke the API and then 24 | // compare the returned reference against an existing baseline (like the built-in array indexer) 25 | // to ensure that the two are the same. These are all managed references, so no need for pinning. 26 | ref string r0 = ref Unsafe.AsRef(in tokens.DangerousGetReference()); 27 | ref string r1 = ref Unsafe.AsRef(in tokens[0]); 28 | 29 | Assert.IsTrue(Unsafe.AreSame(ref r0, ref r1)); 30 | } 31 | 32 | [TestMethod] 33 | public void Test_ArrayExtensions_DangerousGetReferenceAt_Zero() 34 | { 35 | string[] tokens = "aa,bb,cc,dd,ee,ff,gg,hh,ii".Split(','); 36 | 37 | ref string r0 = ref Unsafe.AsRef(in tokens.DangerousGetReference()); 38 | ref string r1 = ref Unsafe.AsRef(in tokens.DangerousGetReferenceAt(0)); 39 | 40 | Assert.IsTrue(Unsafe.AreSame(ref r0, ref r1)); 41 | } 42 | 43 | [TestMethod] 44 | public void Test_ArrayExtensions_DangerousGetReferenceAt_Index() 45 | { 46 | string[] tokens = "aa,bb,cc,dd,ee,ff,gg,hh,ii".Split(','); 47 | 48 | ref string r0 = ref Unsafe.AsRef(in tokens.DangerousGetReferenceAt(5)); 49 | ref string r1 = ref Unsafe.AsRef(in tokens[5]); 50 | 51 | Assert.IsTrue(Unsafe.AreSame(ref r0, ref r1)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_ArrayExtensions.3D.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Runtime.CompilerServices; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | namespace CommunityToolkit.HighPerformance.UnitTests.Extensions; 9 | 10 | public partial class Test_ArrayExtensions 11 | { 12 | [TestMethod] 13 | public void Test_ArrayExtensions_3D_DangerousGetReference_Int() 14 | { 15 | int[,,] array = new int[10, 20, 12]; 16 | 17 | // See comments in Test_ArrayExtensions.1D for how these tests work 18 | ref int r0 = ref array.DangerousGetReference(); 19 | ref int r1 = ref array[0, 0, 0]; 20 | 21 | Assert.IsTrue(Unsafe.AreSame(ref r0, ref r1)); 22 | } 23 | 24 | [TestMethod] 25 | public void Test_ArrayExtensions_3D_DangerousGetReference_String() 26 | { 27 | string[,,] array = new string[10, 20, 12]; 28 | 29 | ref string r0 = ref array.DangerousGetReference(); 30 | ref string r1 = ref array[0, 0, 0]; 31 | 32 | Assert.IsTrue(Unsafe.AreSame(ref r0, ref r1)); 33 | } 34 | 35 | [TestMethod] 36 | public void Test_ArrayExtensions_3D_DangerousGetReferenceAt_Zero() 37 | { 38 | int[,,] array = new int[10, 20, 12]; 39 | 40 | ref int r0 = ref array.DangerousGetReferenceAt(0, 0, 0); 41 | ref int r1 = ref array[0, 0, 0]; 42 | 43 | Assert.IsTrue(Unsafe.AreSame(ref r0, ref r1)); 44 | } 45 | 46 | [TestMethod] 47 | public void Test_ArrayExtensions_3D_DangerousGetReferenceAt_Index() 48 | { 49 | int[,,] array = new int[10, 20, 12]; 50 | 51 | ref int r0 = ref array.DangerousGetReferenceAt(5, 3, 4); 52 | ref int r1 = ref array[5, 3, 4]; 53 | 54 | Assert.IsTrue(Unsafe.AreSame(ref r0, ref r1)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_BoolExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | namespace CommunityToolkit.HighPerformance.UnitTests.Extensions; 9 | 10 | [TestClass] 11 | public class Test_BoolExtensions 12 | { 13 | [TestMethod] 14 | public void Test_BoolExtensions_True() 15 | { 16 | // There tests all just run a couple of boolean expressions and validate that the extension 17 | // correctly produces either 1 or 0 depending on whether the expression was true or false. 18 | Assert.AreEqual(1, true.ToByte(), nameof(Test_BoolExtensions_True)); 19 | Assert.AreEqual(1, (DateTime.Now.Year > 0).ToByte(), nameof(Test_BoolExtensions_True)); 20 | } 21 | 22 | [TestMethod] 23 | public void Test_BoolExtensions_False() 24 | { 25 | Assert.AreEqual(0, false.ToByte(), nameof(Test_BoolExtensions_False)); 26 | Assert.AreEqual(0, (DateTime.Now.Year > 3000).ToByte(), nameof(Test_BoolExtensions_False)); 27 | } 28 | 29 | [TestMethod] 30 | [DataRow(true, -1)] 31 | [DataRow(false, 0)] 32 | public void Test_BoolExtensions_ToBitwiseMask32(bool value, int result) 33 | { 34 | Assert.AreEqual(value.ToBitwiseMask32(), result); 35 | } 36 | 37 | [TestMethod] 38 | [DataRow(true, -1)] 39 | [DataRow(false, 0)] 40 | public void Test_BoolExtensions_ToBitwiseMask64(bool value, long result) 41 | { 42 | Assert.AreEqual(value.ToBitwiseMask64(), result); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_IMemoryOwnerExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.IO; 6 | using CommunityToolkit.HighPerformance.Buffers; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | 9 | namespace CommunityToolkit.HighPerformance.UnitTests.Extensions; 10 | 11 | [TestClass] 12 | public class Test_IMemoryOwnerExtensions 13 | { 14 | [TestMethod] 15 | public void Test_IMemoryOwnerExtensions_EmptyIMemoryOwnerStream() 16 | { 17 | MemoryOwner buffer = MemoryOwner.Empty; 18 | 19 | Stream stream = buffer.AsStream(); 20 | 21 | Assert.IsNotNull(stream); 22 | Assert.AreEqual(buffer.Length, 0); 23 | Assert.AreEqual(stream.Length, 0); 24 | Assert.IsTrue(stream.CanWrite); 25 | } 26 | 27 | [TestMethod] 28 | public void Test_MemoryExtensions_IMemoryOwnerStream() 29 | { 30 | MemoryOwner buffer = MemoryOwner.Allocate(1024); 31 | 32 | Stream stream = buffer.AsStream(); 33 | 34 | Assert.IsNotNull(stream); 35 | Assert.AreEqual(stream.Length, buffer.Length); 36 | Assert.IsTrue(stream.CanWrite); 37 | } 38 | 39 | [TestMethod] 40 | public void Test_MemoryExtensions_IMemoryOwnerStream_DoesNotAlterExistingData() 41 | { 42 | MemoryOwner buffer = MemoryOwner.Allocate(1024); 43 | 44 | // Fill the buffer with sample data 45 | for (int i = 0; i < buffer.Length; i++) 46 | { 47 | buffer.Span[i] = unchecked((byte)(i & byte.MaxValue)); 48 | } 49 | 50 | Stream stream = buffer.AsStream(); 51 | 52 | Assert.IsNotNull(stream); 53 | Assert.AreEqual(stream.Length, buffer.Length); 54 | Assert.IsTrue(stream.CanWrite); 55 | 56 | // Validate that creating the stream doesn't alter the underlying buffer 57 | for (int i = 0; i < buffer.Length; i++) 58 | { 59 | Assert.AreEqual(buffer.Span[i], unchecked((byte)(i & byte.MaxValue))); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_ReadOnlyMemoryExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.IO; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | 9 | namespace CommunityToolkit.HighPerformance.UnitTests.Extensions; 10 | 11 | [TestClass] 12 | public class Test_ReadOnlyMemoryExtensions 13 | { 14 | [TestMethod] 15 | public void Test_ReadOnlyMemoryExtensions_EmptyMemoryStream() 16 | { 17 | ReadOnlyMemory memory = default; 18 | 19 | Stream stream = memory.AsStream(); 20 | 21 | Assert.IsNotNull(stream); 22 | Assert.AreEqual(stream.Length, memory.Length); 23 | Assert.IsFalse(stream.CanWrite); 24 | } 25 | 26 | [TestMethod] 27 | public void Test_ReadOnlyMemoryExtensions_MemoryStream() 28 | { 29 | ReadOnlyMemory memory = new byte[1024]; 30 | 31 | Stream stream = memory.AsStream(); 32 | 33 | Assert.IsNotNull(stream); 34 | Assert.AreEqual(stream.Length, memory.Length); 35 | Assert.IsFalse(stream.CanWrite); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_SpinLockExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | 9 | #pragma warning disable CS0618 10 | 11 | namespace CommunityToolkit.HighPerformance.UnitTests.Extensions; 12 | 13 | [TestClass] 14 | public class Test_SpinLockExtensions 15 | { 16 | [TestMethod] 17 | public unsafe void Test_ArrayExtensions_Pointer() 18 | { 19 | SpinLock spinLock = default; 20 | SpinLock* p = &spinLock; 21 | 22 | int sum = 0; 23 | 24 | _ = Parallel.For(0, 1000, i => 25 | { 26 | for (int j = 0; j < 10; j++) 27 | { 28 | using (SpinLockExtensions.Enter(p)) 29 | { 30 | sum++; 31 | } 32 | } 33 | }); 34 | 35 | Assert.AreEqual(sum, 1000 * 10); 36 | } 37 | 38 | #if NET7_0_OR_GREATER 39 | [TestMethod] 40 | public void Test_ArrayExtensions_Ref() 41 | { 42 | SpinLockOwner? spinLockOwner = new(); 43 | 44 | int sum = 0; 45 | 46 | _ = Parallel.For(0, 1000, i => 47 | { 48 | for (int j = 0; j < 10; j++) 49 | { 50 | using (spinLockOwner.Lock.Enter()) 51 | { 52 | sum++; 53 | } 54 | } 55 | }); 56 | 57 | Assert.AreEqual(sum, 1000 * 10); 58 | } 59 | 60 | /// 61 | /// A dummy model that owns a object. 62 | /// 63 | private sealed class SpinLockOwner 64 | { 65 | public SpinLock Lock; 66 | } 67 | #endif 68 | } 69 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_StringExtensions.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Runtime.CompilerServices; 7 | using CommunityToolkit.HighPerformance; 8 | using Microsoft.VisualStudio.TestTools.UnitTesting; 9 | 10 | namespace CommunityToolkit.HighPerformance.UnitTests.Extensions; 11 | 12 | [TestClass] 13 | public class Test_StringExtensions 14 | { 15 | [TestMethod] 16 | public void Test_StringExtensions_DangerousGetReference() 17 | { 18 | string text = "Hello, world!"; 19 | 20 | ref char r0 = ref text.DangerousGetReference(); 21 | ref char r1 = ref Unsafe.AsRef(in text.AsSpan()[0]); 22 | 23 | Assert.IsTrue(Unsafe.AreSame(ref r0, ref r1)); 24 | } 25 | 26 | [TestMethod] 27 | public void Test_StringExtensions_DangerousGetReferenceAt_Zero() 28 | { 29 | string text = "Hello, world!"; 30 | 31 | ref char r0 = ref text.DangerousGetReference(); 32 | ref char r1 = ref text.DangerousGetReferenceAt(0); 33 | 34 | Assert.IsTrue(Unsafe.AreSame(ref r0, ref r1)); 35 | } 36 | 37 | [TestMethod] 38 | public void Test_StringExtensions_DangerousGetReferenceAt_Index() 39 | { 40 | string text = "Hello, world!"; 41 | 42 | ref char r0 = ref text.DangerousGetReferenceAt(5); 43 | ref char r1 = ref Unsafe.AsRef(in text.AsSpan()[5]); 44 | 45 | Assert.IsTrue(Unsafe.AreSame(ref r0, ref r1)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Helpers/Test_ParallelHelper.ForEach.In.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Runtime.CompilerServices; 7 | using System.Threading; 8 | using CommunityToolkit.HighPerformance.Helpers; 9 | using Microsoft.VisualStudio.TestTools.UnitTesting; 10 | using CommunityToolkit.HighPerformance.UnitTests.Buffers.Internals; 11 | 12 | namespace CommunityToolkit.HighPerformance.UnitTests.Helpers; 13 | 14 | public partial class Test_ParallelHelper 15 | { 16 | [TestMethod] 17 | public unsafe void Test_ParallelHelper_ForEach_In() 18 | { 19 | foreach (int count in TestForCounts) 20 | { 21 | using UnmanagedSpanOwner data = CreateRandomData(count); 22 | 23 | int sum = 0; 24 | 25 | ParallelHelper.ForEach(data.Memory, new Summer(&sum)); 26 | 27 | int expected = 0; 28 | 29 | foreach (int n in data.GetSpan()) 30 | { 31 | expected += n; 32 | } 33 | 34 | Assert.AreEqual(sum, expected, $"The sum doesn't match, was {sum} instead of {expected}"); 35 | } 36 | } 37 | 38 | /// 39 | /// A type implementing to sum array elements. 40 | /// 41 | private readonly unsafe struct Summer : IInAction 42 | { 43 | private readonly int* ptr; 44 | 45 | public Summer(int* ptr) => this.ptr = ptr; 46 | 47 | /// 48 | public void Invoke(in int i) => Interlocked.Add(ref Unsafe.AsRef(this.ptr), i); 49 | } 50 | 51 | /// 52 | /// Creates a random array filled with random numbers. 53 | /// 54 | /// The number of array items to create. 55 | /// An array of random elements. 56 | private static UnmanagedSpanOwner CreateRandomData(int count) 57 | { 58 | Random? random = new(count); 59 | 60 | UnmanagedSpanOwner data = new(count); 61 | 62 | foreach (ref int n in data.GetSpan()) 63 | { 64 | n = random.Next(0, byte.MaxValue); 65 | } 66 | 67 | return data; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Helpers/Test_ParallelHelper.ForEach.Ref.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using CommunityToolkit.HighPerformance.Helpers; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | using CommunityToolkit.HighPerformance.UnitTests.Buffers.Internals; 9 | 10 | namespace CommunityToolkit.HighPerformance.UnitTests.Helpers; 11 | 12 | public partial class Test_ParallelHelper 13 | { 14 | [TestMethod] 15 | public void Test_ParallelHelper_ForEach_Ref() 16 | { 17 | foreach (int count in TestForCounts) 18 | { 19 | using UnmanagedSpanOwner data = CreateRandomData(count); 20 | using UnmanagedSpanOwner copy = new(count); 21 | 22 | data.GetSpan().CopyTo(copy.GetSpan()); 23 | 24 | foreach (ref int n in copy.GetSpan()) 25 | { 26 | n = unchecked(n * 397); 27 | } 28 | 29 | ParallelHelper.ForEach(data.Memory, new Multiplier(397)); 30 | 31 | Span dataSpan = data.GetSpan(); 32 | Span copySpan = copy.GetSpan(); 33 | 34 | for (int i = 0; i < data.Length; i++) 35 | { 36 | if (dataSpan[i] != copySpan[i]) 37 | { 38 | Assert.Fail($"Item #{i} was not a match, was {dataSpan[i]} instead of {copySpan[i]}"); 39 | } 40 | } 41 | } 42 | } 43 | 44 | /// 45 | /// A type implementing to multiply array elements. 46 | /// 47 | private readonly struct Multiplier : IRefAction 48 | { 49 | private readonly int factor; 50 | 51 | public Multiplier(int factor) => this.factor = factor; 52 | 53 | /// 54 | public void Invoke(ref int i) => i = unchecked(i * this.factor); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Helpers/Test_ParallelHelper.ForEach.Ref2D.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.HighPerformance.Helpers; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | namespace CommunityToolkit.HighPerformance.UnitTests.Helpers; 9 | 10 | public partial class Test_ParallelHelper 11 | { 12 | [TestMethod] 13 | [DataRow(1, 1, 0, 0, 1, 1)] 14 | [DataRow(1, 2, 0, 0, 1, 2)] 15 | [DataRow(2, 3, 0, 0, 2, 3)] 16 | [DataRow(2, 3, 0, 1, 2, 2)] 17 | [DataRow(3, 3, 1, 1, 2, 2)] 18 | [DataRow(12, 12, 2, 4, 3, 3)] 19 | [DataRow(64, 64, 0, 0, 32, 32)] 20 | [DataRow(64, 64, 13, 14, 23, 22)] 21 | public void Test_ParallelHelper_ForEach_Ref2D( 22 | int sizeY, 23 | int sizeX, 24 | int row, 25 | int column, 26 | int height, 27 | int width) 28 | { 29 | int[,] data = CreateRandomData2D(sizeY, sizeX); 30 | int[,] copy = (int[,])data.Clone(); 31 | 32 | // Prepare the target data iteratively 33 | foreach (ref int n in copy.AsSpan2D(row, column, height, width)) 34 | { 35 | n = unchecked(n * 397); 36 | } 37 | 38 | Memory2D memory = data.AsMemory2D(row, column, height, width); 39 | 40 | Assert.AreEqual(memory.Length, height * width); 41 | Assert.AreEqual(memory.Height, height); 42 | Assert.AreEqual(memory.Width, width); 43 | 44 | // Do the same computation in parallel, then compare the two arrays 45 | ParallelHelper.ForEach(memory, new Multiplier(397)); 46 | 47 | CollectionAssert.AreEqual(data, copy); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Streams/Test_IMemoryOwnerStream.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.IO; 7 | using CommunityToolkit.HighPerformance.Buffers; 8 | using Microsoft.VisualStudio.TestTools.UnitTesting; 9 | 10 | namespace CommunityToolkit.HighPerformance.UnitTests.Streams; 11 | 12 | [TestClass] 13 | public class Test_IMemoryOwnerStream 14 | { 15 | [TestMethod] 16 | public void Test_IMemoryOwnerStream_Lifecycle() 17 | { 18 | MemoryOwner buffer = MemoryOwner.Allocate(100); 19 | 20 | Stream stream = buffer.AsStream(); 21 | 22 | Assert.IsTrue(stream.CanRead); 23 | Assert.IsTrue(stream.CanSeek); 24 | Assert.IsTrue(stream.CanWrite); 25 | Assert.AreEqual(stream.Length, buffer.Length); 26 | Assert.AreEqual(stream.Position, 0); 27 | 28 | stream.Dispose(); 29 | 30 | _ = Assert.ThrowsException(() => buffer.Memory); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Test_NullableRef{T}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | #if NET7_0_OR_GREATER 6 | 7 | using System; 8 | using System.Runtime.CompilerServices; 9 | using Microsoft.VisualStudio.TestTools.UnitTesting; 10 | 11 | namespace CommunityToolkit.HighPerformance.UnitTests; 12 | 13 | [TestClass] 14 | public class Test_NullableRefOfT 15 | { 16 | [TestMethod] 17 | public void Test_NullableRefOfT_CreateNullableRefOfT_Ok() 18 | { 19 | int value = 1; 20 | NullableRef reference = new(ref value); 21 | 22 | Assert.IsTrue(reference.HasValue); 23 | Assert.IsTrue(Unsafe.AreSame(ref value, ref reference.Value)); 24 | 25 | reference.Value++; 26 | 27 | Assert.AreEqual(value, 2); 28 | } 29 | 30 | [TestMethod] 31 | public void Test_NullableRefOfT_CreateNullableRefOfT_Null() 32 | { 33 | Assert.IsFalse(default(NullableRef).HasValue); 34 | Assert.IsFalse(NullableRef.Null.HasValue); 35 | 36 | Assert.IsFalse(default(NullableRef).HasValue); 37 | Assert.IsFalse(NullableRef.Null.HasValue); 38 | } 39 | 40 | [TestMethod] 41 | [ExpectedException(typeof(InvalidOperationException))] 42 | public void Test_NullableRefOfT_CreateNullableRefOfT_Null_Exception() 43 | { 44 | NullableRef reference = default; 45 | 46 | _ = reference.Value; 47 | } 48 | 49 | [TestMethod] 50 | public void Test_NullableRefOfT_CreateNullableRefOfT_ImplicitRefCast() 51 | { 52 | int value = 42; 53 | Ref reference = new(ref value); 54 | NullableRef nullableRef = reference; 55 | 56 | Assert.IsTrue(nullableRef.HasValue); 57 | Assert.IsTrue(Unsafe.AreSame(ref reference.Value, ref nullableRef.Value)); 58 | } 59 | 60 | [TestMethod] 61 | public void Test_NullableRefOfT_CreateNullableRefOfT_ExplicitCastOfT() 62 | { 63 | int value = 42; 64 | NullableRef reference = new(ref value); 65 | 66 | Assert.AreEqual(value, (int)reference); 67 | } 68 | 69 | [TestMethod] 70 | [ExpectedException(typeof(InvalidOperationException))] 71 | public void Test_NullableRefOfT_CreateNullableRefOfT_ExplicitCastOfT_Exception() 72 | { 73 | NullableRef invalid = default; 74 | 75 | _ = (int)invalid; 76 | } 77 | } 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Test_ReadOnlyRef{T}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | #if NET7_0_OR_GREATER 6 | 7 | using System.Runtime.CompilerServices; 8 | using Microsoft.VisualStudio.TestTools.UnitTesting; 9 | 10 | namespace CommunityToolkit.HighPerformance.UnitTests; 11 | 12 | [TestClass] 13 | public class Test_ReadOnlyRefOfT 14 | { 15 | [TestMethod] 16 | public void Test_RefOfT_CreateRefOfT() 17 | { 18 | int value = 1; 19 | ReadOnlyRef reference = new(value); 20 | 21 | Assert.IsTrue(Unsafe.AreSame(ref value, ref Unsafe.AsRef(in reference.Value))); 22 | } 23 | } 24 | 25 | #endif -------------------------------------------------------------------------------- /tests/CommunityToolkit.HighPerformance.UnitTests/Test_Ref{T}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | #if NET7_0_OR_GREATER 6 | 7 | using System.Runtime.CompilerServices; 8 | using Microsoft.VisualStudio.TestTools.UnitTesting; 9 | 10 | namespace CommunityToolkit.HighPerformance.UnitTests; 11 | 12 | [TestClass] 13 | public class Test_RefOfT 14 | { 15 | [TestMethod] 16 | public void Test_RefOfT_CreateRefOfT() 17 | { 18 | int value = 1; 19 | Ref reference = new(ref value); 20 | 21 | Assert.IsTrue(Unsafe.AreSame(ref value, ref reference.Value)); 22 | 23 | reference.Value++; 24 | 25 | Assert.AreEqual(value, 2); 26 | } 27 | } 28 | 29 | #endif -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.DisableINotifyPropertyChanging.UnitTests/CommunityToolkit.Mvvm.DisableINotifyPropertyChanging.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;net7.0;net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.DisableINotifyPropertyChanging.UnitTests/Test_DisableINotifyPropertyChanging.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.ComponentModel; 7 | using CommunityToolkit.Mvvm.ComponentModel; 8 | using Microsoft.VisualStudio.TestTools.UnitTesting; 9 | 10 | namespace CommunityToolkit.Mvvm.DisableINotifyPropertyChanging.UnitTests; 11 | 12 | [TestClass] 13 | public class Test_DisableINotifyPropertyChanging 14 | { 15 | static Test_DisableINotifyPropertyChanging() 16 | { 17 | AppContext.SetSwitch("MVVMTOOLKIT_ENABLE_INOTIFYPROPERTYCHANGING_SUPPORT", false); 18 | } 19 | 20 | [TestMethod] 21 | public void Test_ObservableObject_Events() 22 | { 23 | SampleModel? model = new(); 24 | 25 | (PropertyChangedEventArgs, int) changed = default; 26 | 27 | model.PropertyChanging += (s, e) => Assert.Fail(); 28 | 29 | model.PropertyChanged += (s, e) => 30 | { 31 | Assert.IsNull(changed.Item1); 32 | Assert.AreSame(model, s); 33 | Assert.IsNotNull(s); 34 | Assert.IsNotNull(e); 35 | 36 | changed = (e, model.Data); 37 | }; 38 | 39 | model.Data = 42; 40 | 41 | Assert.AreEqual(changed.Item1?.PropertyName, nameof(SampleModel.Data)); 42 | Assert.AreEqual(changed.Item2, 42); 43 | } 44 | 45 | public class SampleModel : ObservableObject 46 | { 47 | private T? data; 48 | 49 | public T? Data 50 | { 51 | get => this.data; 52 | set => SetProperty(ref this.data, value); 53 | } 54 | 55 | protected override void OnPropertyChanging(PropertyChangingEventArgs e) 56 | { 57 | Assert.Fail(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.ExternalAssembly.Roslyn4001/CommunityToolkit.Mvvm.ExternalAssembly.Roslyn4001.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 9 | 10 | false 11 | false 12 | $(NoWarn);CS8002;SA0001 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.ExternalAssembly.Roslyn4031/CommunityToolkit.Mvvm.ExternalAssembly.Roslyn4031.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | false 9 | false 10 | $(NoWarn);CS8002;SA0001 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.ExternalAssembly/CommunityToolkit.Mvvm.ExternalAssembly.projitems: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | e827a9cd-405f-43e4-84c7-68cc7e845cdc 7 | 8 | 9 | CommunityToolkit.Mvvm.ExternalAssembly 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.ExternalAssembly/CommunityToolkit.Mvvm.ExternalAssembly.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | e827a9cd-405f-43e4-84c7-68cc7e845cdc 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.ExternalAssembly/ModelWithObservableObjectAttribute.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Mvvm.ComponentModel; 6 | 7 | #pragma warning disable MVVMTK0033 8 | 9 | namespace CommunityToolkit.Mvvm.ExternalAssembly; 10 | 11 | /// 12 | /// Test viewmodel for https://github.com/CommunityToolkit/dotnet/issues/222. 13 | /// 14 | [ObservableObject] 15 | public partial class ModelWithObservableObjectAttribute 16 | { 17 | [ObservableProperty] 18 | private string? _myProperty; 19 | } -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.ExternalAssembly/ModelWithObservablePropertyAndMethod.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Mvvm.ComponentModel; 6 | 7 | namespace CommunityToolkit.Mvvm.ExternalAssembly; 8 | 9 | /// 10 | /// Test viewmodel for https://github.com/CommunityToolkit/dotnet/issues/222. 11 | /// 12 | public abstract partial class ModelWithObservablePropertyAndMethod : ObservableObject 13 | { 14 | [ObservableProperty] 15 | private bool canSave; 16 | 17 | /// 18 | /// Base method to then generate a command. 19 | /// 20 | public abstract void Save(); 21 | } 22 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.ExternalAssembly/SampleModelWithINPCAndObservableProperties.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Mvvm.ComponentModel; 6 | 7 | #pragma warning disable MVVMTK0032 8 | 9 | namespace CommunityToolkit.Mvvm.ExternalAssembly; 10 | 11 | /// 12 | /// See https://github.com/CommunityToolkit/WindowsCommunityToolkit/issues/4167. 13 | /// This model in particular is loaded from an external .NET Standard 2.0 assembly. 14 | /// 15 | [INotifyPropertyChanged] 16 | public partial class SampleModelWithINPCAndObservableProperties 17 | { 18 | [ObservableProperty] 19 | private int x; 20 | 21 | [ObservableProperty] 22 | private int y; 23 | } 24 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.Internals.UnitTests/CommunityToolkit.Mvvm.Internals.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;net7.0;net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.Roslyn4001.UnitTests/CommunityToolkit.Mvvm.Roslyn4001.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;net7.0;net8.0 5 | true 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.Roslyn4031.UnitTests/CommunityToolkit.Mvvm.Roslyn4031.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;net7.0;net8.0 5 | true 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.Roslyn4120.UnitTests/CommunityToolkit.Mvvm.Roslyn4120.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;net7.0;net8.0 5 | preview 6 | true 7 | $(DefineConstants);ROSLYN_4_12_0_OR_GREATER 8 | 9 | 10 | $(NoWarn);MVVMTK0042 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.SourceGenerators.Roslyn4001.UnitTests/CommunityToolkit.Mvvm.SourceGenerators.Roslyn4001.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;net7.0;net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.SourceGenerators.Roslyn4001.UnitTests/Test_UnsupportedRoslynVersionForPartialPropertyAnalyzer.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading.Tasks; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | 9 | namespace CommunityToolkit.Mvvm.SourceGenerators.UnitTests; 10 | 11 | [TestClass] 12 | public class Test_UnsupportedRoslynVersionForPartialPropertyAnalyzer 13 | { 14 | [TestMethod] 15 | public async Task UnsupportedRoslynVersionForPartialPropertyAnalyzer_Warns() 16 | { 17 | const string source = """ 18 | using CommunityToolkit.Mvvm.ComponentModel; 19 | 20 | namespace MyApp 21 | { 22 | public partial class SampleViewModel : ObservableObject 23 | { 24 | [ObservableProperty] 25 | public string {|MVVMTK0044:Bar|} { get; set; } 26 | } 27 | } 28 | """; 29 | 30 | await Test_SourceGeneratorsDiagnostics.VerifyAnalyzerDiagnosticsAndSuccessfulGeneration(source, LanguageVersion.CSharp8); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.SourceGenerators.Roslyn4031.UnitTests/CommunityToolkit.Mvvm.SourceGenerators.Roslyn4031.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;net7.0;net8.0 5 | $(DefineConstants);ROSLYN_4_3_1_OR_GREATER 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.SourceGenerators.Roslyn4120.UnitTests/CommunityToolkit.Mvvm.SourceGenerators.Roslyn4120.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;net7.0;net8.0 5 | $(DefineConstants);ROSLYN_4_3_1_OR_GREATER;ROSLYN_4_12_0_OR_GREATER 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests.projitems: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | fb59ce88-7732-4a63-b5bd-ac5681b7da1a 7 | 8 | 9 | CommunityToolkit.Mvvm.SourceGenerators.UnitTests 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | fb59ce88-7732-4a63-b5bd-ac5681b7da1a 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/Helpers/CSharpCodeFixWithLanguageVersionTest{TAnalyzer,TCodeFix,TVerifier}.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Microsoft.CodeAnalysis.CSharp; 6 | using Microsoft.CodeAnalysis.Diagnostics; 7 | using Microsoft.CodeAnalysis.Testing; 8 | using Microsoft.CodeAnalysis; 9 | using Microsoft.CodeAnalysis.CodeFixes; 10 | using Microsoft.CodeAnalysis.CSharp.Testing; 11 | 12 | namespace CommunityToolkit.Mvvm.SourceGenerators.UnitTests.Helpers; 13 | 14 | /// 15 | /// A custom that uses a specific C# language version to parse code. 16 | /// 17 | /// The type of the analyzer to produce diagnostics. 18 | /// The type of code fix to test. 19 | /// The type of verifier to use to validate the code fixer. 20 | internal sealed class CSharpCodeFixWithLanguageVersionTest : CSharpCodeFixTest 21 | where TAnalyzer : DiagnosticAnalyzer, new() 22 | where TCodeFix : CodeFixProvider, new() 23 | where TVerifier : IVerifier, new() 24 | { 25 | /// 26 | /// The C# language version to use to parse code. 27 | /// 28 | private readonly LanguageVersion languageVersion; 29 | 30 | /// 31 | /// Creates a new instance with the specified parameters. 32 | /// 33 | /// The C# language version to use to parse code. 34 | public CSharpCodeFixWithLanguageVersionTest(LanguageVersion languageVersion) 35 | { 36 | this.languageVersion = languageVersion; 37 | } 38 | 39 | /// 40 | protected override ParseOptions CreateParseOptions() 41 | { 42 | return new CSharpParseOptions(this.languageVersion, DocumentationMode.Diagnose); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.UnitTests/Collections/IntGroup.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | namespace CommunityToolkit.Mvvm.UnitTests; 9 | 10 | /// 11 | /// A simple implementation for and values. 12 | /// 13 | internal sealed class IntGroup : List, IGrouping 14 | { 15 | /// 16 | /// Creates a new instance with the specified parameters. 17 | /// 18 | /// The group key. 19 | /// The group values. 20 | public IntGroup(string key, IEnumerable collection) 21 | : base(collection) 22 | { 23 | Key = key; 24 | } 25 | 26 | /// 27 | public string Key { get; } 28 | } 29 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.UnitTests/Collections/Test_ObservableGroupedCollection.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using CommunityToolkit.Mvvm.Collections; 9 | using Microsoft.VisualStudio.TestTools.UnitTesting; 10 | 11 | namespace CommunityToolkit.Mvvm.UnitTests.Collections; 12 | 13 | [TestClass] 14 | public class Test_ObservableGroupedCollection 15 | { 16 | [TestMethod] 17 | public void Test_ObservableGroupedCollection_Ctor_ShouldHaveExpectedValues() 18 | { 19 | ObservableGroupedCollection groupCollection = new(); 20 | 21 | Assert.AreEqual(groupCollection.Count, 0); 22 | } 23 | 24 | [TestMethod] 25 | public void Test_ObservableGroupedCollection_Ctor_WithGroups_ShouldHaveExpectedValues() 26 | { 27 | List> groups = new() 28 | { 29 | new IntGroup("A", new[] { 1, 3, 5 }), 30 | new IntGroup("B", new[] { 2, 4, 6 }), 31 | }; 32 | ObservableGroupedCollection groupCollection = new(groups); 33 | 34 | Assert.AreEqual(groupCollection.Count, 2); 35 | 36 | Assert.AreEqual(groupCollection[0].Key, "A"); 37 | CollectionAssert.AreEqual(groupCollection[0], new[] { 1, 3, 5 }); 38 | 39 | Assert.AreEqual(groupCollection[1].Key, "B"); 40 | CollectionAssert.AreEqual(groupCollection[1], new[] { 2, 4, 6 }); 41 | } 42 | 43 | [TestMethod] 44 | [ExpectedException(typeof(ArgumentNullException))] 45 | public void Test_ObservableGroupedCollection_Ctor_NullCollection() 46 | { 47 | _ = new ObservableGroupedCollection(null!); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.UnitTests/CommunityToolkit.Mvvm.UnitTests.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | b8dcd82e-b53b-4249-ad4e-f9b99acb9334 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.UnitTests/Helpers/ExceptionHelper.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | namespace CommunityToolkit.Mvvm.UnitTests.Helpers; 9 | 10 | /// 11 | /// A helper class to validate scenarios related to -s. 12 | /// 13 | internal static class ExceptionHelper 14 | { 15 | /// 16 | /// Asserts that a given action throws an with a specific parameter name. 17 | /// 18 | /// The input to invoke. 19 | /// The expected parameter name. 20 | public static void ThrowsArgumentExceptionWithParameterName(Action action, string parameterName) 21 | { 22 | bool success = false; 23 | 24 | try 25 | { 26 | action(); 27 | } 28 | catch (Exception e) 29 | { 30 | Assert.IsTrue(e.GetType() == typeof(ArgumentException)); 31 | Assert.AreEqual(parameterName, ((ArgumentException)e).ParamName); 32 | 33 | success = true; 34 | } 35 | 36 | Assert.IsTrue(success); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.UnitTests/Test_ArgumentNullException.DependencyInjection.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Mvvm.DependencyInjection; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | 8 | namespace CommunityToolkit.Mvvm.UnitTests; 9 | 10 | public partial class Test_ArgumentNullException 11 | { 12 | [TestMethod] 13 | public void Test_ArgumentNullException_Ioc() 14 | { 15 | Ioc ioc = new(); 16 | 17 | Assert(() => ioc.GetService(serviceType: null!), "serviceType"); 18 | Assert(() => ioc.ConfigureServices(serviceProvider: null!), "serviceProvider"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservablePropertyAttribute.RootNamespace.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using CommunityToolkit.Mvvm.ComponentModel; 6 | 7 | // Test viewmodel for https://github.com/CommunityToolkit/dotnet/issues/271 8 | internal partial class ModelWithObservablePropertyInRootNamespace : ObservableObject 9 | { 10 | [ObservableProperty] 11 | private float number; 12 | } -------------------------------------------------------------------------------- /tests/CommunityToolkit.Mvvm.UnitTests/Test_RelayCommand.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using CommunityToolkit.Mvvm.Input; 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | 9 | namespace CommunityToolkit.Mvvm.UnitTests; 10 | 11 | [TestClass] 12 | public class Test_RelayCommand 13 | { 14 | [TestMethod] 15 | public void Test_RelayCommand_AlwaysEnabled() 16 | { 17 | int ticks = 0; 18 | 19 | RelayCommand? command = new(() => ticks++); 20 | 21 | Assert.IsTrue(command.CanExecute(null)); 22 | Assert.IsTrue(command.CanExecute(new object())); 23 | 24 | (object?, EventArgs?) args = default; 25 | 26 | command.CanExecuteChanged += (s, e) => args = (s, e); 27 | 28 | command.NotifyCanExecuteChanged(); 29 | 30 | Assert.AreSame(args.Item1, command); 31 | Assert.AreSame(args.Item2, EventArgs.Empty); 32 | 33 | command.Execute(null); 34 | 35 | Assert.AreEqual(ticks, 1); 36 | 37 | command.Execute(new object()); 38 | 39 | Assert.AreEqual(ticks, 2); 40 | } 41 | 42 | [TestMethod] 43 | public void Test_RelayCommand_WithCanExecuteFunctionTrue() 44 | { 45 | int ticks = 0; 46 | 47 | RelayCommand? command = new(() => ticks++, () => true); 48 | 49 | Assert.IsTrue(command.CanExecute(null)); 50 | Assert.IsTrue(command.CanExecute(new object())); 51 | 52 | command.Execute(null); 53 | 54 | Assert.AreEqual(ticks, 1); 55 | 56 | command.Execute(new object()); 57 | 58 | Assert.AreEqual(ticks, 2); 59 | } 60 | 61 | [TestMethod] 62 | public void Test_RelayCommand_WithCanExecuteFunctionFalse() 63 | { 64 | int ticks = 0; 65 | 66 | RelayCommand? command = new(() => ticks++, () => false); 67 | 68 | Assert.IsFalse(command.CanExecute(null)); 69 | Assert.IsFalse(command.CanExecute(new object())); 70 | 71 | command.Execute(null); 72 | 73 | // Logic is unconditionally invoked, the caller should check CanExecute first 74 | Assert.AreEqual(ticks, 1); 75 | 76 | command.Execute(new object()); 77 | 78 | Assert.AreEqual(ticks, 2); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /toolkit.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommunityToolkit/dotnet/657c6971a8d42655c648336b781639ed96c2c49f/toolkit.snk -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "8.4.0-build.{height}", 3 | "publicReleaseRefSpec": [ 4 | "^refs/heads/main$", // we release out of main 5 | "^refs/heads/dev$", // we release out of dev 6 | "^refs/heads/rel/\\d+\\.\\d+\\.\\d+" // we also release branches starting with rel/N.N.N 7 | ], 8 | "nugetPackageVersion": { 9 | "semVer": 2 10 | }, 11 | "cloudBuild": { 12 | "buildNumber": { 13 | "enabled": false 14 | } 15 | } 16 | } 17 | --------------------------------------------------------------------------------