From 84c3e291bac3997c494ce26cca48ebc5edbcd5b4 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Mon, 13 Dec 2021 18:06:07 +0100 Subject: [PATCH] Port incremental helpers from ComputeSharp Also added attribution in ThirdPartyNotices.txt --- .../Diagnostics/DiagnosticExtensions.cs | 56 +++++++++++- .../Extensions/AttributeDataExtensions.cs | 3 + .../Extensions/HashCodeExtensions.cs | 47 ++++++++++ .../IncrementalValuesProviderExtensions.cs | 78 ++++++++++++++++ .../Models/HierarchyInfo.cs | 91 +++++++++++++++++++ .../Models/Result.cs | 19 ++++ ThirdPartyNotices.txt | 29 +++++- 7 files changed, 320 insertions(+), 3 deletions(-) create mode 100644 CommunityToolkit.Mvvm.SourceGenerators/Extensions/HashCodeExtensions.cs create mode 100644 CommunityToolkit.Mvvm.SourceGenerators/Extensions/IncrementalValuesProviderExtensions.cs create mode 100644 CommunityToolkit.Mvvm.SourceGenerators/Models/HierarchyInfo.cs create mode 100644 CommunityToolkit.Mvvm.SourceGenerators/Models/Result.cs diff --git a/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/DiagnosticExtensions.cs b/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/DiagnosticExtensions.cs index 4f43874..56f16c6 100644 --- a/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/DiagnosticExtensions.cs +++ b/CommunityToolkit.Mvvm.SourceGenerators/Diagnostics/DiagnosticExtensions.cs @@ -2,6 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +// This file is ported and adapted from ComputeSharp (Sergio0694/ComputeSharp), +// more info in ThirdPartyNotices.txt in the root of the project. + +using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis; @@ -15,7 +19,7 @@ internal static class DiagnosticExtensions /// /// Adds a new diagnostics to the current compilation. /// - /// The instance currently in use. + /// The instance currently in use. /// The input for the diagnostics to create. /// The source to attach the diagnostics to. /// The optional arguments for the formatted message to include. @@ -31,7 +35,7 @@ internal static class DiagnosticExtensions /// /// Adds a new diagnostics to the current compilation. /// - /// The instance currently in use. + /// The instance currently in use. /// The input for the diagnostics to create. /// The source to attach the diagnostics to. /// The optional arguments for the formatted message to include. @@ -43,4 +47,52 @@ internal static class DiagnosticExtensions { context.ReportDiagnostic(Diagnostic.Create(descriptor, node.GetLocation(), args)); } + + /// + /// Adds a new diagnostics to the target builder. + /// + /// The collection of produced instances. + /// The input for the diagnostics to create. + /// The source to attach the diagnostics to. + /// The optional arguments for the formatted message to include. + public static void Add( + this ImmutableArray.Builder diagnostics, + DiagnosticDescriptor descriptor, + ISymbol symbol, + params object[] args) + { + diagnostics.Add(Diagnostic.Create(descriptor, symbol.Locations.FirstOrDefault(), args)); + } + + /// + /// Adds a new diagnostics to the target builder. + /// + /// The collection of produced instances. + /// The input for the diagnostics to create. + /// The source to attach the diagnostics to. + /// The optional arguments for the formatted message to include. + public static void Add( + this ImmutableArray.Builder diagnostics, + DiagnosticDescriptor descriptor, + SyntaxNode node, + params object[] args) + { + diagnostics.Add(Diagnostic.Create(descriptor, node.GetLocation(), args)); + } + + /// + /// Registers an output node into an to output diagnostics. + /// + /// The input instance. + /// The input sequence of diagnostics. + public static void ReportDiagnostics(this IncrementalGeneratorInitializationContext context, IncrementalValuesProvider> diagnostics) + { + context.RegisterSourceOutput(diagnostics, static (context, diagnostics) => + { + foreach (Diagnostic diagnostic in diagnostics) + { + context.ReportDiagnostic(diagnostic); + } + }); + } } diff --git a/CommunityToolkit.Mvvm.SourceGenerators/Extensions/AttributeDataExtensions.cs b/CommunityToolkit.Mvvm.SourceGenerators/Extensions/AttributeDataExtensions.cs index be35b29..ff69632 100644 --- a/CommunityToolkit.Mvvm.SourceGenerators/Extensions/AttributeDataExtensions.cs +++ b/CommunityToolkit.Mvvm.SourceGenerators/Extensions/AttributeDataExtensions.cs @@ -2,6 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +// This file is ported and adapted from ComputeSharp (Sergio0694/ComputeSharp), +// more info in ThirdPartyNotices.txt in the root of the project. + using System; using System.Collections.Generic; using System.Linq; diff --git a/CommunityToolkit.Mvvm.SourceGenerators/Extensions/HashCodeExtensions.cs b/CommunityToolkit.Mvvm.SourceGenerators/Extensions/HashCodeExtensions.cs new file mode 100644 index 0000000..32e0fd6 --- /dev/null +++ b/CommunityToolkit.Mvvm.SourceGenerators/Extensions/HashCodeExtensions.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// This file is ported and adapted from ComputeSharp (Sergio0694/ComputeSharp), +// more info in ThirdPartyNotices.txt in the root of the project. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions; + +/// +/// Extension methods for . +/// +internal static class HashCodeExtensions +{ + /// + /// Adds all items from a given instance to an hashcode. + /// + /// The type of items to hash. + /// The target instance. + /// The input items to hash. + public static void AddRange(this ref HashCode hashCode, ImmutableArray items) + { + foreach (T item in items) + { + hashCode.Add(item); + } + } + + /// + /// Adds all items from a given instance to an hashcode. + /// + /// The type of items to hash. + /// The target instance. + /// A comparer to get hashcodes for items. + /// The input items to hash. + public static void AddRange(this ref HashCode hashCode, ImmutableArray items, IEqualityComparer comparer) + { + foreach (T item in items) + { + hashCode.Add(item, comparer); + } + } +} \ No newline at end of file diff --git a/CommunityToolkit.Mvvm.SourceGenerators/Extensions/IncrementalValuesProviderExtensions.cs b/CommunityToolkit.Mvvm.SourceGenerators/Extensions/IncrementalValuesProviderExtensions.cs new file mode 100644 index 0000000..be9f446 --- /dev/null +++ b/CommunityToolkit.Mvvm.SourceGenerators/Extensions/IncrementalValuesProviderExtensions.cs @@ -0,0 +1,78 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// This file is ported and adapted from ComputeSharp (Sergio0694/ComputeSharp), +// more info in ThirdPartyNotices.txt in the root of the project. + +using System; +using System.Collections.Generic; +using Microsoft.CodeAnalysis; + +namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions; + +/// +/// Extension methods for . +/// +internal static class IncrementalValuesProviderExtensions +{ + /// + /// Creates a new instance with a gven pair of comparers. + /// + /// The type of left items in each tuple. + /// The type of right items in each tuple. + /// The input instance. + /// An instance for items. + /// An instance for items. + /// An with the specified comparers applied to each item. + public static IncrementalValuesProvider<(TLeft Left, TRight Right)> WithComparers( + this IncrementalValuesProvider<(TLeft Left, TRight Right)> source, + IEqualityComparer comparerLeft, + IEqualityComparer comparerRight) + { + return source.WithComparer(new Comparer(comparerLeft, comparerRight)); + } + + /// + /// An implementation for a value tuple. + /// + public sealed class Comparer : IEqualityComparer<(TLeft Left, TRight Right)> + { + /// + /// The comparer. + /// + private readonly IEqualityComparer comparerLeft; + + /// + /// The comparer. + /// + private readonly IEqualityComparer comparerRight; + + /// + /// Creates a new instance with the specified parameters. + /// + /// The comparer. + /// The comparer. + public Comparer(IEqualityComparer comparerLeft, IEqualityComparer comparerRight) + { + this.comparerLeft = comparerLeft; + this.comparerRight = comparerRight; + } + + /// + public bool Equals((TLeft Left, TRight Right) x, (TLeft Left, TRight Right) y) + { + return + this.comparerLeft.Equals(x.Left, y.Left) && + this.comparerRight.Equals(x.Right, y.Right); + } + + /// + public int GetHashCode((TLeft Left, TRight Right) obj) + { + return HashCode.Combine( + this.comparerLeft.GetHashCode(obj.Left), + this.comparerRight.GetHashCode(obj.Right)); + } + } +} diff --git a/CommunityToolkit.Mvvm.SourceGenerators/Models/HierarchyInfo.cs b/CommunityToolkit.Mvvm.SourceGenerators/Models/HierarchyInfo.cs new file mode 100644 index 0000000..aa7ba22 --- /dev/null +++ b/CommunityToolkit.Mvvm.SourceGenerators/Models/HierarchyInfo.cs @@ -0,0 +1,91 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// This file is ported and adapted from ComputeSharp (Sergio0694/ComputeSharp), +// more info in ThirdPartyNotices.txt in the root of the project. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using CommunityToolkit.Mvvm.SourceGenerators.Extensions; +using Microsoft.CodeAnalysis; +using static Microsoft.CodeAnalysis.SymbolDisplayTypeQualificationStyle; + +namespace CommunityToolkit.Mvvm.SourceGenerators.Models; + +/// +/// A model describing the hierarchy info for a specific type. +/// +/// The filename hint for the current type. +/// The metadata name for the current type. +/// Gets the namespace for the current type. +/// Gets the sequence of type definitions containing the current type. +internal sealed record HierarchyInfo(string FilenameHint, string MetadataName, string Namespace, ImmutableArray Names) +{ + /// + /// Creates a new instance from a given . + /// + /// The input instance to gather info for. + /// A instance describing . + public static HierarchyInfo From(INamedTypeSymbol typeSymbol) + { + ImmutableArray.Builder names = ImmutableArray.CreateBuilder(); + + for (INamedTypeSymbol? parent = typeSymbol; + parent is not null; + parent = parent.ContainingType) + { + names.Add(parent.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)); + } + + return new( + typeSymbol.GetFullMetadataNameForFileName(), + typeSymbol.MetadataName, + typeSymbol.ContainingNamespace.ToDisplayString(new(typeQualificationStyle: NameAndContainingTypesAndNamespaces)), + names.ToImmutable()); + } + + /// + /// An implementation for . + /// + public sealed class Comparer : IEqualityComparer + { + /// + /// The singleton instance. + /// + public static Comparer Default { get; } = new(); + + /// + public bool Equals(HierarchyInfo? x, HierarchyInfo? y) + { + if (x is null && y is null) + { + return true; + } + + if (x is null || y is null) + { + return false; + } + + if (ReferenceEquals(x, y)) + { + return true; + } + + return + x.FilenameHint == y.FilenameHint && + x.MetadataName == y.MetadataName && + x.Namespace == y.Namespace && + x.Names.SequenceEqual(y.Names); + } + + /// + public int GetHashCode(HierarchyInfo obj) + { + return HashCode.Combine(obj.Namespace, obj.MetadataName, obj.Names, obj.Names[0]); + } + } +} diff --git a/CommunityToolkit.Mvvm.SourceGenerators/Models/Result.cs b/CommunityToolkit.Mvvm.SourceGenerators/Models/Result.cs new file mode 100644 index 0000000..83ca3d1 --- /dev/null +++ b/CommunityToolkit.Mvvm.SourceGenerators/Models/Result.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// This file is ported and adapted from ComputeSharp (Sergio0694/ComputeSharp), +// more info in ThirdPartyNotices.txt in the root of the project. + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; + +namespace CommunityToolkit.Mvvm.SourceGenerators.Models; + +/// +/// A model representing a value and an associated set of diagnostic errors. +/// +/// The type of the wrapped value. +/// The wrapped value for the current result. +/// The associated diagnostic errors, if any. +internal sealed record Result(TValue Value, ImmutableArray Errors); diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index 057c784..ea8b9da 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -11,6 +11,7 @@ This project incorporates components from the projects listed below. The origina 4. PrivateObject/PrivateType (https://github.com/microsoft/testfx/tree/664ac7c2ac9dbfbee9d2a0ef560cfd72449dfe34/src/TestFramework/Extension.Desktop), included in UnitTests. 5. QuinnDamerell/UniversalMarkdown (https://github.com/QuinnDamerell/UniversalMarkdown) contributed by Quinn Damerell and Paul Bartrum for the MarkdownTextBlock control, relicensed to this .NET Foundation project under the MIT license upon contribution in https://github.com/CommunityToolkit/WindowsCommunityToolkit/pull/772. 6. qmatteoq/DesktopBridgeHelpers commit e278153 (https://github.com/qmatteoq/DesktopBridgeHelpers), contributed by Matteo Pagani to identify if running with identity in DesktopNotificationManagerCompat.cs and DesktopBridgeHelpers.cs, relicensed to this .NET Foundation project under the MIT license upon contribution in https://github.com/CommunityToolkit/WindowsCommunityToolkit/pull/3457. +7. Sergio0694/ComputeSharp (https://github.com/Sergio0694/ComputeSharp), contributed by Sergio Pedri to reuse some helpers to support incremental generators in the MVVM Toolkit. %% PedroLamas/DeferredEvents NOTICES AND INFORMATION BEGIN HERE ========================================= @@ -113,4 +114,30 @@ 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. ========================================= -END OF PrivateOject/PrivateType NOTICES AND INFORMATION \ No newline at end of file +END OF PrivateOject/PrivateType NOTICES AND INFORMATION + +%% Sergio0694/ComputeSharp NOTICES AND INFORMATION BEGIN HERE +========================================= +MIT License + +Copyright (c) 2021 Sergio Pedri + +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: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +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 NONINFRINGEMENT. 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. +========================================= +END OF Sergio0694/ComputeSharp NOTICES AND INFORMATION \ No newline at end of file