From 6e78f5aab8782a6e93ab19733e3a6bb9b7a66d5d Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Wed, 22 Feb 2023 08:28:14 -0600 Subject: [PATCH] Store WellKnownTypeProvider (from dotnet/roslyn-analyzers) in TagHelperDescriptorProviderContext --- ...omponentTagHelperDescriptorProviderTest.cs | 2 +- ...omponentTagHelperDescriptorProviderTest.cs | 2 +- ...omponentTagHelperDescriptorProviderTest.cs | 2 +- .../src/CompilationTagHelperFeature.cs | 5 +- .../src/PublicAPI.Unshipped.txt | 1 + .../src/SymbolExtensions.cs | 49 ++- .../src/SymbolVisibility.cs | 12 + .../src/SymbolVisibilityExtensions.cs | 32 ++ ...lperDescriptorProviderContextExtensions.cs | 15 +- .../src/WellKnownTypeNames.cs | 9 + .../src/WellKnownTypeProvider.cs | 291 ++++++++++++++++++ .../BaseTagHelperDescriptorProviderTest.cs | 3 + .../BindTagHelperDescriptorProviderTest.cs | 22 +- ...omponentTagHelperDescriptorProviderTest.cs | 54 ++-- .../DefaultTagHelperDescriptorProviderTest.cs | 6 +- ...tHandlerTagHelperDescriptorProviderTest.cs | 2 +- .../KeyTagHelperDescriptorProviderTest.cs | 2 +- .../RefTagHelperDescriptorProviderTest.cs | 2 +- .../SplatTagHelperDescriptorProviderTest.cs | 2 +- .../RazorSourceGenerator.TagHelpers.cs | 37 --- .../RazorSourceGenerator.cs | 21 +- .../StaticCompilationTagHelperFeature.cs | 6 +- .../TagHelperResolver.cs | 2 +- 23 files changed, 477 insertions(+), 102 deletions(-) create mode 100644 src/Compiler/Microsoft.CodeAnalysis.Razor/src/SymbolVisibility.cs create mode 100644 src/Compiler/Microsoft.CodeAnalysis.Razor/src/SymbolVisibilityExtensions.cs create mode 100644 src/Compiler/Microsoft.CodeAnalysis.Razor/src/WellKnownTypeNames.cs create mode 100644 src/Compiler/Microsoft.CodeAnalysis.Razor/src/WellKnownTypeProvider.cs delete mode 100644 src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.TagHelpers.cs diff --git a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/test/ViewComponentTagHelperDescriptorProviderTest.cs b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/test/ViewComponentTagHelperDescriptorProviderTest.cs index ba263154902..472cf919cb5 100644 --- a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/test/ViewComponentTagHelperDescriptorProviderTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X/test/ViewComponentTagHelperDescriptorProviderTest.cs @@ -30,7 +30,7 @@ public class StringParameterViewComponent var compilation = MvcShim.BaseCompilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(code)); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ViewComponentTagHelperDescriptorProvider() { diff --git a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/ViewComponentTagHelperDescriptorProviderTest.cs b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/ViewComponentTagHelperDescriptorProviderTest.cs index 065025367d0..46ffb1fb713 100644 --- a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/ViewComponentTagHelperDescriptorProviderTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X/test/ViewComponentTagHelperDescriptorProviderTest.cs @@ -31,7 +31,7 @@ public class StringParameterViewComponent var compilation = MvcShim.BaseCompilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(code)); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ViewComponentTagHelperDescriptorProvider() { diff --git a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/ViewComponentTagHelperDescriptorProviderTest.cs b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/ViewComponentTagHelperDescriptorProviderTest.cs index c2e72ff3e72..fd3f3ec388b 100644 --- a/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/ViewComponentTagHelperDescriptorProviderTest.cs +++ b/src/Compiler/Microsoft.AspNetCore.Mvc.Razor.Extensions/test/ViewComponentTagHelperDescriptorProviderTest.cs @@ -28,7 +28,7 @@ public class StringParameterViewComponent var compilation = MvcShim.BaseCompilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(code)); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ViewComponentTagHelperDescriptorProvider() { diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/src/CompilationTagHelperFeature.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/CompilationTagHelperFeature.cs index 09ca7e652ef..ebaec74cbed 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor/src/CompilationTagHelperFeature.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/CompilationTagHelperFeature.cs @@ -4,6 +4,7 @@ #nullable disable using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis.CSharp; @@ -23,7 +24,7 @@ public IReadOnlyList GetDescriptors() var compilation = CSharpCompilation.Create("__TagHelpers", references: _referenceFeature.References); if (IsValidCompilation(compilation)) { - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); } for (var i = 0; i < _providers.Length; i++) @@ -40,7 +41,7 @@ protected override void OnInitialized() _providers = Engine.Features.OfType().OrderBy(f => f.Order).ToArray(); } - internal static bool IsValidCompilation(Compilation compilation) + internal static bool IsValidCompilation([NotNullWhen(true)] Compilation compilation) { var @string = compilation.GetSpecialType(SpecialType.System_String); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/src/PublicAPI.Unshipped.txt b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/PublicAPI.Unshipped.txt index ab058de62d4..b2bbf3462cb 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor/src/PublicAPI.Unshipped.txt +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/PublicAPI.Unshipped.txt @@ -1 +1,2 @@ #nullable enable +*REMOVED*~static Microsoft.CodeAnalysis.Razor.TagHelperDescriptorProviderContextExtensions.SetCompilation(this Microsoft.AspNetCore.Razor.Language.TagHelperDescriptorProviderContext context, Microsoft.CodeAnalysis.Compilation compilation) -> void diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/src/SymbolExtensions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/SymbolExtensions.cs index c6056b8d906..dadf7a1ad83 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor/src/SymbolExtensions.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/SymbolExtensions.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; @@ -16,4 +16,51 @@ internal static bool HasFullName(this ISymbol symbol, string fullName) { return symbol.ToDisplayString(FullNameTypeDisplayFormat).Equals(fullName, StringComparison.Ordinal); } + + internal static SymbolVisibility GetResultantVisibility(this ISymbol symbol) + { + // Start by assuming it's visible. + SymbolVisibility visibility = SymbolVisibility.Public; + + switch (symbol.Kind) + { + case SymbolKind.Alias: + // Aliases are uber private. They're only visible in the same file that they + // were declared in. + return SymbolVisibility.Private; + + case SymbolKind.Parameter: + // Parameters are only as visible as their containing symbol + return GetResultantVisibility(symbol.ContainingSymbol); + + case SymbolKind.TypeParameter: + // Type Parameters are private. + return SymbolVisibility.Private; + } + + while (symbol != null && symbol.Kind != SymbolKind.Namespace) + { + switch (symbol.DeclaredAccessibility) + { + // If we see anything private, then the symbol is private. + case Accessibility.NotApplicable: + case Accessibility.Private: + return SymbolVisibility.Private; + + // If we see anything internal, then knock it down from public to + // internal. + case Accessibility.Internal: + case Accessibility.ProtectedAndInternal: + visibility = SymbolVisibility.Internal; + break; + + // For anything else (Public, Protected, ProtectedOrInternal), the + // symbol stays at the level we've gotten so far. + } + + symbol = symbol.ContainingSymbol; + } + + return visibility; + } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/src/SymbolVisibility.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/SymbolVisibility.cs new file mode 100644 index 00000000000..be56a83ba4f --- /dev/null +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/SymbolVisibility.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.CodeAnalysis.Razor; + +internal enum SymbolVisibility +{ + Public = 0, + Internal = 1, + Private = 2, + Friend = Internal, +} diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/src/SymbolVisibilityExtensions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/SymbolVisibilityExtensions.cs new file mode 100644 index 00000000000..b1e45c5e6e7 --- /dev/null +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/SymbolVisibilityExtensions.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.CodeAnalysis.Razor; + +/// +/// Extensions for . +/// +internal static class SymbolVisibilityExtensions +{ + /// + /// Determines whether is at least as visible as . + /// + /// The visibility to compare against. + /// The visibility to compare with. + /// True if one can say that is at least as visible as . + /// + /// For example, is at least as visible as , but is not as visible as . + /// + public static bool IsAtLeastAsVisibleAs(this SymbolVisibility typeVisibility, SymbolVisibility comparisonVisibility) + { + return typeVisibility switch + { + SymbolVisibility.Public => true, + SymbolVisibility.Internal => comparisonVisibility != SymbolVisibility.Public, + SymbolVisibility.Private => comparisonVisibility == SymbolVisibility.Private, + _ => throw new ArgumentOutOfRangeException(nameof(typeVisibility), typeVisibility, null), + }; + } +} diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/src/TagHelperDescriptorProviderContextExtensions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/TagHelperDescriptorProviderContextExtensions.cs index 23273e15454..c972fd83ff3 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor/src/TagHelperDescriptorProviderContextExtensions.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/TagHelperDescriptorProviderContextExtensions.cs @@ -20,13 +20,24 @@ public static Compilation GetCompilation(this TagHelperDescriptorProviderContext return (Compilation)context.Items[typeof(Compilation)]; } - public static void SetCompilation(this TagHelperDescriptorProviderContext context, Compilation compilation) + public static WellKnownTypeProvider GetTypeProvider(this TagHelperDescriptorProviderContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } - context.Items[typeof(Compilation)] = compilation; + return (WellKnownTypeProvider)context.Items[typeof(WellKnownTypeProvider)]; + } + + public static void SetTypeProvider(this TagHelperDescriptorProviderContext context, WellKnownTypeProvider typeProvider) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + context.Items[typeof(Compilation)] = typeProvider.Compilation; + context.Items[typeof(WellKnownTypeProvider)] = typeProvider; } } diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/src/WellKnownTypeNames.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/WellKnownTypeNames.cs new file mode 100644 index 00000000000..39300933cb7 --- /dev/null +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/WellKnownTypeNames.cs @@ -0,0 +1,9 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.CodeAnalysis.Razor; + +internal static class WellKnownTypeNames +{ + public const string SystemThreadingTasksTask1 = "System.Threading.Tasks.Task`1"; +} diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/src/WellKnownTypeProvider.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/WellKnownTypeProvider.cs new file mode 100644 index 00000000000..e3d7fa9feba --- /dev/null +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/src/WellKnownTypeProvider.cs @@ -0,0 +1,291 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Linq; +using System.Threading; + +namespace Microsoft.CodeAnalysis.Razor; + +/// +/// Provides and caches well known types in a compilation. +/// +public class WellKnownTypeProvider +{ + public WellKnownTypeProvider(Compilation compilation) + { + Compilation = compilation; + _fullNameToTypeMap = new ConcurrentDictionary(StringComparer.Ordinal); + _referencedAssemblies = new Lazy>( + () => + { + return ImmutableHashSet.Create( + SymbolEqualityComparer.Default, + Compilation.Assembly.Modules + .SelectMany(m => m.ReferencedAssemblySymbols) + .ToArray()); + }, + LazyThreadSafetyMode.ExecutionAndPublication); + } + + public Compilation Compilation { get; } + + /// + /// All the referenced assembly symbols. + /// + /// + /// Seems to be less memory intensive than: + /// foreach (Compilation.Assembly.Modules) + /// foreach (Module.ReferencedAssemblySymbols) + /// + private readonly Lazy> _referencedAssemblies; + + /// + /// Mapping of full name to . + /// + private readonly ConcurrentDictionary _fullNameToTypeMap; + + /// + /// Static cache of full type names (with namespaces) to namespace name parts, + /// so we can query . + /// + /// + /// Example: "System.Collections.Generic.List`1" => [ "System", "Collections", "Generic" ] + /// + /// https://github.com/dotnet/roslyn/blob/9e786147b8cb884af454db081bb747a5bd36a086/src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs#L455 + /// suggests the TypeNames collection can be checked to avoid expensive operations. But realizing TypeNames seems to be + /// as memory intensive as unnecessary calls GetTypeByMetadataName() in some cases. So we'll go with namespace names. + /// + private static readonly ConcurrentDictionary> _fullTypeNameToNamespaceNames = + new(StringComparer.Ordinal); + + /// + /// Attempts to get the type by the full type name. + /// + /// Namespace + type name, e.g. "System.Exception". + /// Named type symbol, if any. + /// True if found in the compilation, false otherwise. + ////[PerformanceSensitive("https://github.com/dotnet/roslyn-analyzers/issues/4893", AllowCaptures = false)] + public bool TryGetOrCreateTypeByMetadataName( + string fullTypeName, + [NotNullWhen(returnValue: true)] out INamedTypeSymbol? namedTypeSymbol) + { + if (_fullNameToTypeMap.TryGetValue(fullTypeName, out namedTypeSymbol)) + { + return namedTypeSymbol is not null; + } + + return TryGetOrCreateTypeByMetadataNameSlow(fullTypeName, out namedTypeSymbol); + } + + private bool TryGetOrCreateTypeByMetadataNameSlow( + string fullTypeName, + [NotNullWhen(returnValue: true)] out INamedTypeSymbol? namedTypeSymbol) + { + namedTypeSymbol = _fullNameToTypeMap.GetOrAdd( + fullTypeName, + fullyQualifiedMetadataName => + { + // Caching null results is intended. + + // sharwell says: Suppose you reference assembly A with public API X.Y, and you reference assembly B with + // internal API X.Y. Even though you can use X.Y from assembly A, compilation.GetTypeByMetadataName will + // fail outright because it finds two types with the same name. + + INamedTypeSymbol? type = null; + + ImmutableArray namespaceNames; + if (string.IsInterned(fullTypeName) != null) + { + namespaceNames = _fullTypeNameToNamespaceNames.GetOrAdd( + fullTypeName, + GetNamespaceNamesFromFullTypeName); + } + else + { + namespaceNames = GetNamespaceNamesFromFullTypeName(fullTypeName); + } + + if (IsSubsetOfCollection(namespaceNames, Compilation.Assembly.NamespaceNames)) + { + type = Compilation.Assembly.GetTypeByMetadataName(fullyQualifiedMetadataName); + } + + if (type is null) + { + Debug.Assert(namespaceNames != null); + + foreach (IAssemblySymbol? referencedAssembly in _referencedAssemblies.Value) + { + if (!IsSubsetOfCollection(namespaceNames, referencedAssembly.NamespaceNames)) + { + continue; + } + + var currentType = referencedAssembly.GetTypeByMetadataName(fullyQualifiedMetadataName); + if (currentType is null) + { + continue; + } + + switch (currentType.GetResultantVisibility()) + { + case SymbolVisibility.Public: + case SymbolVisibility.Internal when referencedAssembly.GivesAccessTo(Compilation.Assembly): + break; + + default: + continue; + } + + if (type is object) + { + // Multiple visible types with the same metadata name are present. + return null; + } + + type = currentType; + } + } + + return type; + }); + + return namedTypeSymbol != null; + } + + /// + /// Gets a type by its full type name. + /// + /// Namespace + type name, e.g. "System.Exception". + /// The if found, null otherwise. + public INamedTypeSymbol? GetOrCreateTypeByMetadataName(string fullTypeName) + { + TryGetOrCreateTypeByMetadataName(fullTypeName, out INamedTypeSymbol? namedTypeSymbol); + return namedTypeSymbol; + } + + /// + /// Determines if is a with its type + /// argument satisfying . + /// + /// Type potentially representing a . + /// Predicate to check the 's type argument. + /// True if is a with its + /// type argument satisfying , false otherwise. + internal bool IsTaskOfType([NotNullWhen(returnValue: true)] ITypeSymbol? typeSymbol, Func typeArgumentPredicate) + { + return typeSymbol != null + && typeSymbol.OriginalDefinition != null + && SymbolEqualityComparer.Default.Equals(typeSymbol.OriginalDefinition, + GetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemThreadingTasksTask1)) + && typeSymbol is INamedTypeSymbol namedTypeSymbol + && namedTypeSymbol.TypeArguments.Length == 1 + && typeArgumentPredicate(namedTypeSymbol.TypeArguments[0]); + } + + private static ImmutableArray GetNamespaceNamesFromFullTypeName(string fullTypeName) + { + var namespaceNamesBuilder = ImmutableArray.CreateBuilder(); + int prevStartIndex = 0; + for (int i = 0; i < fullTypeName.Length; i++) + { + if (fullTypeName[i] == '.') + { + namespaceNamesBuilder.Add(fullTypeName[prevStartIndex..i]); + prevStartIndex = i + 1; + } + else if (!IsIdentifierPartCharacter(fullTypeName[i])) + { + break; + } + } + + return namespaceNamesBuilder.ToImmutable(); + } + + /// + /// Returns true if the Unicode character can be a part of an identifier. + /// + /// The Unicode character. + private static bool IsIdentifierPartCharacter(char ch) + { + // identifier-part-character: + // letter-character + // decimal-digit-character + // connecting-character + // combining-character + // formatting-character + + if (ch < 'a') // '\u0061' + { + if (ch < 'A') // '\u0041' + { + return ch is >= '0' // '\u0030' + and <= '9'; // '\u0039' + } + + return ch is <= 'Z' // '\u005A' + or '_'; // '\u005F' + } + + if (ch <= 'z') // '\u007A' + { + return true; + } + + if (ch <= '\u007F') // max ASCII + { + return false; + } + + UnicodeCategory cat = CharUnicodeInfo.GetUnicodeCategory(ch); + + ////return IsLetterChar(cat) + //// || IsDecimalDigitChar(cat) + //// || IsConnectingChar(cat) + //// || IsCombiningChar(cat) + //// || IsFormattingChar(cat); + + return cat switch + { + // Letter + UnicodeCategory.UppercaseLetter + or UnicodeCategory.LowercaseLetter + or UnicodeCategory.TitlecaseLetter + or UnicodeCategory.ModifierLetter + or UnicodeCategory.OtherLetter + or UnicodeCategory.LetterNumber + or UnicodeCategory.DecimalDigitNumber + or UnicodeCategory.ConnectorPunctuation + or UnicodeCategory.NonSpacingMark + or UnicodeCategory.SpacingCombiningMark + or UnicodeCategory.Format => true, + _ => false, + }; + } + + private static bool IsSubsetOfCollection(ImmutableArray set1, ICollection set2) + { + if (set1.Length > set2.Count) + { + return false; + } + + for (int i = 0; i < set1.Length; i++) + { + if (!set2.Contains(set1[i])) + { + return false; + } + } + + return true; + } +} diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/BaseTagHelperDescriptorProviderTest.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/BaseTagHelperDescriptorProviderTest.cs index 3478ce8e9ce..783aaaae4c9 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/BaseTagHelperDescriptorProviderTest.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/BaseTagHelperDescriptorProviderTest.cs @@ -18,11 +18,14 @@ public abstract class TagHelperDescriptorProviderTestBase static TagHelperDescriptorProviderTestBase() { BaseCompilation = TestCompilation.Create(typeof(ComponentTagHelperDescriptorProviderTest).Assembly); + BaseTypeProvider = new WellKnownTypeProvider(BaseCompilation); CSharpParseOptions = new CSharpParseOptions(LanguageVersion.CSharp7_3); } protected static Compilation BaseCompilation { get; } + protected static WellKnownTypeProvider BaseTypeProvider { get; } + protected static CSharpParseOptions CSharpParseOptions { get; } protected static CSharpSyntaxTree Parse(string text) diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/BindTagHelperDescriptorProviderTest.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/BindTagHelperDescriptorProviderTest.cs index 0dd4c38ef17..5e90e3a0fb5 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/BindTagHelperDescriptorProviderTest.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/BindTagHelperDescriptorProviderTest.cs @@ -50,7 +50,7 @@ public Task SetParametersAsync(ParameterView parameters) Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); // We run after component discovery and depend on the results. var componentProvider = new ComponentTagHelperDescriptorProvider(); @@ -203,7 +203,7 @@ public Task SetParametersAsync(ParameterView parameters) Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); // We run after component discovery and depend on the results. var componentProvider = new ComponentTagHelperDescriptorProvider(); @@ -354,7 +354,7 @@ public Task SetParametersAsync(ParameterView parameters) Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); // We run after component discovery and depend on the results. var componentProvider = new ComponentTagHelperDescriptorProvider(); @@ -390,7 +390,7 @@ public class BindAttributes Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new BindTagHelperDescriptorProvider(); @@ -651,7 +651,7 @@ public class BindAttributes Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new BindTagHelperDescriptorProvider(); @@ -736,7 +736,7 @@ public class BindAttributes Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new BindTagHelperDescriptorProvider(); @@ -812,7 +812,7 @@ public class BindAttributes Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new BindTagHelperDescriptorProvider(); @@ -909,7 +909,7 @@ public class BindAttributes Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new BindTagHelperDescriptorProvider(); @@ -1008,7 +1008,7 @@ public class BindAttributes Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new BindTagHelperDescriptorProvider(); @@ -1033,11 +1033,11 @@ public class BindAttributes public void Execute_BindFallback_CreatesDescriptor() { // Arrange - var compilation = BaseCompilation; + var (compilation, typeProvider) = (BaseCompilation, BaseTypeProvider); Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(typeProvider); var provider = new BindTagHelperDescriptorProvider(); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/ComponentTagHelperDescriptorProviderTest.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/ComponentTagHelperDescriptorProviderTest.cs index b233dd10a41..96947c2b5bb 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/ComponentTagHelperDescriptorProviderTest.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/ComponentTagHelperDescriptorProviderTest.cs @@ -42,7 +42,7 @@ public Task SetParametersAsync(ParameterView parameters) Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -167,7 +167,7 @@ public Task SetParametersAsync(ParameterView parameters) Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -231,7 +231,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -273,7 +273,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -313,7 +313,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -353,7 +353,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -406,7 +406,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -454,7 +454,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -502,7 +502,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -566,7 +566,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -641,7 +641,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -691,7 +691,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -753,7 +753,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -804,7 +804,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -859,7 +859,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -922,7 +922,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -979,7 +979,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -1054,7 +1054,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -1126,7 +1126,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -1208,7 +1208,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -1290,7 +1290,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -1376,7 +1376,7 @@ public class Context Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -1462,7 +1462,7 @@ public class MyComponent : ComponentBase Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -1554,7 +1554,7 @@ public string this[int i] Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -1610,7 +1610,7 @@ public class MyDerivedComponent2 : MyDerivedComponent1 Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); @@ -1670,7 +1670,7 @@ public Task SetParametersAsync(ParameterView parameters) Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); context.Items.SetTargetSymbol((IAssemblySymbol)compilation.GetAssemblyOrModuleSymbol(compilation.References.First(r => r.Display.Contains("Microsoft.CodeAnalysis.Razor.Test.dll")))); var provider = new ComponentTagHelperDescriptorProvider(); @@ -1716,7 +1716,7 @@ public Task SetParametersAsync(ParameterView parameters) Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new ComponentTagHelperDescriptorProvider(); // Act diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/DefaultTagHelperDescriptorProviderTest.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/DefaultTagHelperDescriptorProviderTest.cs index eec507e0ae8..09823d84285 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/DefaultTagHelperDescriptorProviderTest.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/DefaultTagHelperDescriptorProviderTest.cs @@ -26,7 +26,7 @@ public void Execute_DoesNotAddEditorBrowsableNeverDescriptorsAtDesignTime() var descriptorProvider = new DefaultTagHelperDescriptorProvider(); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); context.ExcludeHidden = true; // Act @@ -74,7 +74,7 @@ public override void Process(TagHelperContext context, TagHelperOutput output) { var descriptorProvider = new DefaultTagHelperDescriptorProvider(); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); // Act descriptorProvider.Execute(context); @@ -105,7 +105,7 @@ public override void Process(TagHelperContext context, TagHelperOutput output) { var descriptorProvider = new DefaultTagHelperDescriptorProvider(); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); context.Items.SetTargetSymbol((IAssemblySymbol)compilation.GetAssemblyOrModuleSymbol(compilation.References.First(r => r.Display.Contains("Microsoft.CodeAnalysis.Razor.Test.dll")))); // Act diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/EventHandlerTagHelperDescriptorProviderTest.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/EventHandlerTagHelperDescriptorProviderTest.cs index afae6922869..69bfd6c85e3 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/EventHandlerTagHelperDescriptorProviderTest.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/EventHandlerTagHelperDescriptorProviderTest.cs @@ -34,7 +34,7 @@ public class EventHandlers Assert.Empty(compilation.GetDiagnostics()); var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); var provider = new EventHandlerTagHelperDescriptorProvider(); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/KeyTagHelperDescriptorProviderTest.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/KeyTagHelperDescriptorProviderTest.cs index ab1547c551a..d6f0b6cc8ed 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/KeyTagHelperDescriptorProviderTest.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/KeyTagHelperDescriptorProviderTest.cs @@ -17,7 +17,7 @@ public void Execute_CreatesDescriptor() { // Arrange var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(BaseCompilation); + context.SetTypeProvider(BaseTypeProvider); var provider = new KeyTagHelperDescriptorProvider(); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/RefTagHelperDescriptorProviderTest.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/RefTagHelperDescriptorProviderTest.cs index 8b424ce3d31..c1db2aa773c 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/RefTagHelperDescriptorProviderTest.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/RefTagHelperDescriptorProviderTest.cs @@ -17,7 +17,7 @@ public void Execute_CreatesDescriptor() { // Arrange var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(BaseCompilation); + context.SetTypeProvider(BaseTypeProvider); var provider = new RefTagHelperDescriptorProvider(); diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/SplatTagHelperDescriptorProviderTest.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/SplatTagHelperDescriptorProviderTest.cs index 66e5380a54c..9ec033e3146 100644 --- a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/SplatTagHelperDescriptorProviderTest.cs +++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/SplatTagHelperDescriptorProviderTest.cs @@ -17,7 +17,7 @@ public void Execute_CreatesDescriptor() { // Arrange var context = TagHelperDescriptorProviderContext.Create(); - context.SetCompilation(BaseCompilation); + context.SetTypeProvider(BaseTypeProvider); var provider = new SplatTagHelperDescriptorProvider(); diff --git a/src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.TagHelpers.cs b/src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.TagHelpers.cs deleted file mode 100644 index b0d30d393c9..00000000000 --- a/src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.TagHelpers.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.CodeAnalysis; - -namespace Microsoft.NET.Sdk.Razor.SourceGenerators -{ - public partial class RazorSourceGenerator - { - private IReadOnlyList GetTagHelpers(IEnumerable references, StaticCompilationTagHelperFeature tagHelperFeature, Compilation compilation) - { - List descriptors = new(); - tagHelperFeature.Compilation = compilation; - foreach (var reference in references) - { - if (compilation.GetAssemblyOrModuleSymbol(reference) is IAssemblySymbol assembly) - { - tagHelperFeature.TargetSymbol = assembly; - descriptors.AddRange(tagHelperFeature.GetDescriptors()); - } - } - return descriptors; - } - - private static IReadOnlyList GetTagHelpersFromCompilation(Compilation compilation, StaticCompilationTagHelperFeature tagHelperFeature, SyntaxTree syntaxTrees) - { - var compilationWithDeclarations = compilation.AddSyntaxTrees(syntaxTrees); - - tagHelperFeature.Compilation = compilationWithDeclarations; - tagHelperFeature.TargetSymbol = compilationWithDeclarations.Assembly; - - return tagHelperFeature.GetDescriptors(); - } - } -} diff --git a/src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.cs b/src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.cs index 4fd80d7e3b6..e1b10a5e854 100644 --- a/src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.cs +++ b/src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/RazorSourceGenerator.cs @@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Razor; namespace Microsoft.NET.Sdk.Razor.SourceGenerators { @@ -22,6 +23,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var analyzerConfigOptions = context.AnalyzerConfigOptionsProvider; var parseOptions = context.ParseOptionsProvider; var compilation = context.CompilationProvider; + var typeProvider = compilation.Select(static (compilation, cancellationToken) => new WellKnownTypeProvider(compilation)); // determine if we should suppress this run and filter out all the additional files if so var isGeneratorSuppressed = context.AnalyzerConfigOptionsProvider.Select(GetSuppressionStatus); @@ -105,7 +107,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var compilationWithDeclarations = compilation.AddSyntaxTrees(generatedDeclarationSyntaxTrees); - tagHelperFeature.Compilation = compilationWithDeclarations; + tagHelperFeature.TypeProvider = new WellKnownTypeProvider(compilationWithDeclarations); tagHelperFeature.TargetSymbol = compilationWithDeclarations.Assembly; var result = (IList)tagHelperFeature.GetDescriptors(); @@ -130,13 +132,15 @@ public void Initialize(IncrementalGeneratorInitializationContext context) return true; }, getHashCode: static a => a.Count); - var tagHelpersFromReferences = compilation + var tagHelpersFromReferences = typeProvider .Combine(razorSourceGeneratorOptions) .Combine(hasRazorFiles) .WithLambdaComparer(static (a, b) => { - var ((compilationA, razorSourceGeneratorOptionsA), hasRazorFilesA) = a; - var ((compilationB, razorSourceGeneratorOptionsB), hasRazorFilesB) = b; + var ((typeProviderA, razorSourceGeneratorOptionsA), hasRazorFilesA) = a; + var ((typeProviderB, razorSourceGeneratorOptionsB), hasRazorFilesB) = b; + var compilationA = typeProviderA.Compilation; + var compilationB = typeProviderB.Compilation; if (!compilationA.References.SequenceEqual(compilationB.References)) { @@ -153,14 +157,15 @@ public void Initialize(IncrementalGeneratorInitializationContext context) static item => { // we'll use the number of references as a hashcode. - var ((compilationA, razorSourceGeneratorOptionsA), hasRazorFilesA) = item; - return compilationA.References.GetHashCode(); + var ((typeProviderA, razorSourceGeneratorOptionsA), hasRazorFilesA) = item; + return typeProviderA.Compilation.References.GetHashCode(); }) .Select(static (pair, _) => { RazorSourceGeneratorEventSource.Log.DiscoverTagHelpersFromReferencesStart(); - var ((compilation, razorSourceGeneratorOptions), hasRazorFiles) = pair; + var ((typeProvider, razorSourceGeneratorOptions), hasRazorFiles) = pair; + var compilation = typeProvider.Compilation; if (!hasRazorFiles) { // If there's no razor code in this app, don't do anything. @@ -172,7 +177,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var discoveryProjectEngine = GetDiscoveryProjectEngine(compilation.References.ToImmutableArray(), tagHelperFeature); List descriptors = new(); - tagHelperFeature.Compilation = compilation; + tagHelperFeature.TypeProvider = typeProvider; foreach (var reference in compilation.References) { if (compilation.GetAssemblyOrModuleSymbol(reference) is IAssemblySymbol assembly) diff --git a/src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/StaticCompilationTagHelperFeature.cs b/src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/StaticCompilationTagHelperFeature.cs index 15d54b36587..4e5a12b4b82 100644 --- a/src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/StaticCompilationTagHelperFeature.cs +++ b/src/Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators/StaticCompilationTagHelperFeature.cs @@ -17,14 +17,14 @@ internal sealed class StaticCompilationTagHelperFeature : RazorEngineFeatureBase public List GetDescriptors() { - if (Compilation is null) + if (TypeProvider is null) { return EmptyList; } var results = new List(); var context = TagHelperDescriptorProviderContext.Create(results); - context.SetCompilation(Compilation); + context.SetTypeProvider(TypeProvider); if (TargetSymbol is not null) { context.Items.SetTargetSymbol(TargetSymbol); @@ -40,7 +40,7 @@ public List GetDescriptors() IReadOnlyList ITagHelperFeature.GetDescriptors() => GetDescriptors(); - public Compilation? Compilation { get; set; } + public WellKnownTypeProvider? TypeProvider { get; set; } public ISymbol? TargetSymbol { get; set; } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/TagHelperResolver.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/TagHelperResolver.cs index 5e85460f646..09c9104183a 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/TagHelperResolver.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/TagHelperResolver.cs @@ -52,7 +52,7 @@ protected async Task GetTagHelpersAsync(Project works var compilation = await workspaceProject.GetCompilationAsync(cancellationToken).ConfigureAwait(false); if (CompilationTagHelperFeature.IsValidCompilation(compilation)) { - context.SetCompilation(compilation); + context.SetTypeProvider(new WellKnownTypeProvider(compilation)); } var timingDictionary = new Dictionary();