diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 8b5fb362b36..b38d2fbce0e 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -8,7 +8,8 @@
/eng/common/ @dotnet/razor-tooling @dotnet/razor-compiler
/eng/Versions.props @dotnet/razor-tooling @dotnet/razor-compiler
/eng/Version.Details.xml @dotnet/razor-tooling @dotnet/razor-compiler
-/eng/SourceBuild* @dotnet/source-build-internal
+/eng/DotNetBuild.props @dotnet/product-construction
+/eng/SourceBuild* @dotnet/source-build
/src/Razor @dotnet/razor-tooling
/src/Compiler @dotnet/razor-compiler
/src/Shared @dotnet/razor-tooling @dotnet/razor-compiler
diff --git a/Directory.Build.props b/Directory.Build.props
index 69a3cd1524c..3556b512a08 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -22,9 +22,9 @@
truetruetrue
- true
+ true$(MSBuildThisFileDirectory)
- true
+ truetruetrue
@@ -40,15 +40,9 @@
false
- true
+ truenet472
-
-
- false
-
+ $(NetCurrent)$(DefaultNetCoreTargetFramework);$(NetPrevious)
@@ -71,7 +65,7 @@
-
+ $(NetCurrent)$(DefaultNetCoreTargetFramework)
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 19c6deb856d..02c9a790a75 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -63,7 +63,6 @@
-
diff --git a/NuGet.config b/NuGet.config
index 7a818f5f188..b5e83791aff 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -67,7 +67,6 @@
-
diff --git a/Razor.Slim.slnf b/Razor.Slim.slnf
index 0563c409be2..0b7ce028aee 100644
--- a/Razor.Slim.slnf
+++ b/Razor.Slim.slnf
@@ -15,7 +15,6 @@
"src\\Compiler\\Microsoft.Net.Compilers.Razor.Toolset\\Microsoft.Net.Compilers.Razor.Toolset.csproj",
"src\\Compiler\\test\\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X\\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X.Compiler.csproj",
"src\\Compiler\\test\\Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X\\Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X.Compiler.csproj",
- "src\\Compiler\\test\\Microsoft.AspNetCore.Razor.Test.MvcShim\\Microsoft.AspNetCore.Razor.Test.MvcShim.Compiler.csproj",
"src\\Compiler\\test\\Microsoft.NET.Sdk.Razor.SourceGenerators.Tests\\Microsoft.NET.Sdk.Razor.SourceGenerators.Test.csproj",
"src\\Compiler\\tools\\Microsoft.AspNetCore.Mvc.Razor.Extensions.Tooling.Internal\\Microsoft.AspNetCore.Mvc.Razor.Extensions.Tooling.Internal.csproj",
"src\\Compiler\\tools\\Microsoft.CodeAnalysis.Razor.Tooling.Internal\\Microsoft.CodeAnalysis.Razor.Tooling.Internal.csproj",
diff --git a/Razor.sln b/Razor.sln
index c9338fafeb3..9e4df49add7 100644
--- a/Razor.sln
+++ b/Razor.sln
@@ -100,10 +100,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.Razor.Sou
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.Razor.SourceGenerators.Test", "src\Compiler\test\Microsoft.NET.Sdk.Razor.SourceGenerators.Tests\Microsoft.NET.Sdk.Razor.SourceGenerators.Test.csproj", "{BD96BB0F-84DE-4A5F-8832-C8EADA36F43A}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Test.MvcShim.Compiler", "src\Compiler\test\Microsoft.AspNetCore.Razor.Test.MvcShim\Microsoft.AspNetCore.Razor.Test.MvcShim.Compiler.csproj", "{2CB7D554-49CE-45AC-97DF-7F8C597BDFA7}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.Compiler", "src\Compiler\test\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib\Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib.Compiler.csproj", "{9FE4A38F-F0E7-45BD-94C1-1DC6FA55BB4A}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X.Compiler", "src\Compiler\test\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X\Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X.Compiler.csproj", "{A0867F6B-3DBB-4743-B241-F59878BFA15D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X.Compiler", "src\Compiler\test\Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X\Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X.Compiler.csproj", "{B040B919-D8E3-4656-BD85-88A541AA893D}"
@@ -410,22 +406,6 @@ Global
{BD96BB0F-84DE-4A5F-8832-C8EADA36F43A}.Release|Any CPU.Build.0 = Release|Any CPU
{BD96BB0F-84DE-4A5F-8832-C8EADA36F43A}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
{BD96BB0F-84DE-4A5F-8832-C8EADA36F43A}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
- {2CB7D554-49CE-45AC-97DF-7F8C597BDFA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2CB7D554-49CE-45AC-97DF-7F8C597BDFA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2CB7D554-49CE-45AC-97DF-7F8C597BDFA7}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
- {2CB7D554-49CE-45AC-97DF-7F8C597BDFA7}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
- {2CB7D554-49CE-45AC-97DF-7F8C597BDFA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2CB7D554-49CE-45AC-97DF-7F8C597BDFA7}.Release|Any CPU.Build.0 = Release|Any CPU
- {2CB7D554-49CE-45AC-97DF-7F8C597BDFA7}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
- {2CB7D554-49CE-45AC-97DF-7F8C597BDFA7}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
- {9FE4A38F-F0E7-45BD-94C1-1DC6FA55BB4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9FE4A38F-F0E7-45BD-94C1-1DC6FA55BB4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9FE4A38F-F0E7-45BD-94C1-1DC6FA55BB4A}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
- {9FE4A38F-F0E7-45BD-94C1-1DC6FA55BB4A}.DebugNoVSIX|Any CPU.Build.0 = Debug|Any CPU
- {9FE4A38F-F0E7-45BD-94C1-1DC6FA55BB4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9FE4A38F-F0E7-45BD-94C1-1DC6FA55BB4A}.Release|Any CPU.Build.0 = Release|Any CPU
- {9FE4A38F-F0E7-45BD-94C1-1DC6FA55BB4A}.ReleaseNoVSIX|Any CPU.ActiveCfg = Release|Any CPU
- {9FE4A38F-F0E7-45BD-94C1-1DC6FA55BB4A}.ReleaseNoVSIX|Any CPU.Build.0 = Release|Any CPU
{A0867F6B-3DBB-4743-B241-F59878BFA15D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0867F6B-3DBB-4743-B241-F59878BFA15D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0867F6B-3DBB-4743-B241-F59878BFA15D}.DebugNoVSIX|Any CPU.ActiveCfg = Debug|Any CPU
@@ -660,8 +640,6 @@ Global
{FB7C870E-A173-4F75-BE63-4EF39C79A759} = {5B60F564-4AD7-4B70-A887-7D91496799A2}
{F5017FD5-EA78-4CD2-A1B6-F534910683F8} = {AA4EE974-E765-4B97-AF35-F734BF9830F6}
{BD96BB0F-84DE-4A5F-8832-C8EADA36F43A} = {AA4EE974-E765-4B97-AF35-F734BF9830F6}
- {2CB7D554-49CE-45AC-97DF-7F8C597BDFA7} = {A5E2E4FA-6087-4C16-BB7A-89E23AA0F4E3}
- {9FE4A38F-F0E7-45BD-94C1-1DC6FA55BB4A} = {A5E2E4FA-6087-4C16-BB7A-89E23AA0F4E3}
{A0867F6B-3DBB-4743-B241-F59878BFA15D} = {A5E2E4FA-6087-4C16-BB7A-89E23AA0F4E3}
{B040B919-D8E3-4656-BD85-88A541AA893D} = {A5E2E4FA-6087-4C16-BB7A-89E23AA0F4E3}
{907EDA43-B4D9-40DA-BA07-8E00DD89FA33} = {FB7C870E-A173-4F75-BE63-4EF39C79A759}
diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml
index 17079041941..a9a7d5fd76a 100644
--- a/azure-pipelines-official.yml
+++ b/azure-pipelines-official.yml
@@ -66,6 +66,8 @@ extends:
name: NetCore1ESPool-Svc-Internal
image: 1es-windows-2022
os: windows
+ policheck:
+ enabled: true
tsa:
enabled: true
configFile: '$(Build.SourcesDirectory)/eng/TSAConfig.gdntsa'
diff --git a/docs/CollectionBestPractices.md b/docs/CollectionBestPractices.md
new file mode 100644
index 00000000000..65e702dbbb6
--- /dev/null
+++ b/docs/CollectionBestPractices.md
@@ -0,0 +1,406 @@
+# Collection Best Practices in Razor
+
+- [Imperative Collections](#imperative-collections)
+- [Immutable Collections](#immutable-collections)
+ - [Using Builders](#using-builders)
+ - [`ImmutableArray`](#immutablearrayt)
+ - [Using `ImmutableArray.Builder`](#using-immutablearraytbuilder)
+ - [Frozen Collections](#frozen-collections)
+- [Array Pools](#array-pools)
+- [Object Pools](#object-pools)
+- [✨It’s Magic! `PooledArrayBuilder`](#its-magic-pooledarraybuildert)
+- [Using LINQ](#using-linq)
+ - [Best Practices](#best-practices)
+- [Meta Tips](#meta-tips)
+
+# Imperative Collections
+- .NET provides many collection types with different characteristics for different purposes.
+- The collections from the System.Collections namespace should be avoided. Never use these unless in some legacy scenario.
+- The collections in System.Collections.Generic are considered the “work horse” collection types for .NET and are
+ suitable for most purposes. They have years of hardening that make them highly efficient choices for most work.
+- Popular imperative collection types include the ones we all use on a regular basis `List`, `HashSet`,
+ `Dictionary`, `Stack`.
+- System.Collections.Concurrent contains collections that are designed for use when thread-safety is needed.
+ In general, these should only be used in particular situations.
+
+> [!WARNING]
+> **Beware of collection growth**
+>
+> The imperative collections generally have more internal storage than needed to allow more items to be added. (This is
+> what is meant by "capacity” vs. “count”). When enough items are added, the internal storage will need to grow. This
+> requires creating larger storage, releasing the previous storage for garbage collection, and copying the existing
+> contents into it, which consumes CPU time. For a larger collection, this can potential happen many times, so it’s
+> important to set the capacity up front to avoid unnecessary internal storage growth.
+
+> [!WARNING]
+> **Avoid exposing collection interfaces**
+>
+> Avoid exposing collections directly via interfaces, such as `IReadOnlyList` and
+> `IReadOnlyDictionary`. The primary reason for this is that these interfaces can result in allocations
+> when they are foreach’d. In general, collections provide a struct enumerator that can be used to foreach that
+> collection without allocating an `IEnumertor` on the heap. However, when going through a collection interface,
+> there isn’t a struct enumerator, so an allocation is likely required to foreach. In fact, many collections, such as
+> `List`, are implemented to just return their struct enumerator when accessed via collection interfaces, resulting
+> in an allocation when the struct enumerator is boxed.
+> - If exposing a collection is necessary, consider whether it might be better to expose a more optimal read-only
+> collection. Instead of `IReadOnlyList`, consider [`ImmutableArray`](#immutablearrayt).
+> - There aren’t many other options when an API calls for exposing an `IReadOnlyDictionary`. In these
+> cases, consider whether it might be better to just avoid exposing the collection altogether and provide APIs that
+> access it. Or, in some cases, it might be necessary to create entirely new collection types. (This is why Razor
+> `TagHelperDescriptors` expose a `MetadataCollection`.)
+
+> [!WARNING]
+> **Be mindful of ToArray()**
+>
+> Calling `ToArray()` on a collection will create a new array and copy content from the collection into it. So, when
+> the exact capacity is known up front, it is an anti-pattern to create a `List` without that capacity, fill it
+> with items and then call `ToArray()` at the end. This results in extra allocations that could be avoided by creating
+> an array and filling it.
+
+# Immutable Collections
+- The .NET immutable collections are provided by the System.Collections.Immutable NuGet package, which provides
+ implementations for .NET, .NET Framework, and .NET Standard 2.0.
+- The collections in the System.Collections.Immutable namespace have a very specific purpose. They are intended to be
+ *persistent* data structures; that is, a data structure that always preserves the previous version of itself when it
+ is modified. Such data structures are effectively immutable, but in hindsight, maybe it would have been better for
+ this namespace to have been called, System.Collections.Persistent?
+ - The term “persistent data structure” was introduced by the 1986 paper,
+ “Making Data Structures Persistent” ([PDF](https://www.cs.cmu.edu/~sleator/papers/making-data-structures-persistent.pdf)).
+ - A highly influential book in the area of persistent data structures is “Purely Functional Data Structures” (1999)
+ by Chris Okasaki ([Amazon](https://www.amazon.com/Purely-Functional-Data-Structures-Okasaki/dp/0521663504)).
+ Okasaki’s original dissertation is available from CMU’s website ([PDF](https://www.cs.cmu.edu/~rwh/students/okasaki.pdf)).
+- Because of their persistency, nearly all of the immutable collections have very different implementations than their
+ imperative counterparts. For example, `List` is implemented using an array, while `ImmutableList` is implemented
+ using a binary tree.
+- Mutating methods on an immutable collection perform “non-destructive mutation”. Instead, of mutating the underlying
+ object, a mutating method like `Add` produces a new instance of the immutable collection. This is similar to how the
+ `String.Replace(...)` API is used.
+- Significant effort has been made to ensure that immutable collections are as efficient as they can be. However, the
+ cost of persistence means that immutable collections are generally assumed to be slower than imperative counterparts.
+
+> [!CAUTION]
+>
+> Because the immutable collections are often implemented using binary trees to achieve persistence, the asymptotic
+> complexity of standard operations can be very surprising. For example, `ImmutableDictionary` access is
+> O(log n) rather than the usual O(1) that would be expected when accessing a hash table data structure, such as
+> `Dictionary`. A similar difference in performance characteristics exists across the various collection
+> types. The following table shows the complexity of accessing a few popular collections types using their indexer.
+>
+> | Immutable collection type | Complexity | Imperative collection type | Complexity |
+> | ----------------------------------------- | ---------- | -------------------------------- | ---------- |
+> | `ImmutableDictionary` | O(log n) | `Dictionary` | O(1) |
+> | `ImmutableHashSet` | O(log n) | `HashSet` | O(1) |
+> | `ImmutableList` | O(log n) | `List` | O(1) |
+> | `ImmutableSortedDictionary` | O(log n) | `SortedDictionary` | O(log n) |
+
+> [!CAUTION]
+> **ToImmutableX() extension methods are not “freeze” methods!**
+>
+> The System.Immutable.Collections package provides several extension methods that produce an immutable collection from
+> an existing collection or sequence. These methods aren’t optimized to reuse the internal storage of other collections
+> in any way. Because of this, the following code is an anti-pattern. In this example, each element is added to a
+> `HashSet` and then the elements of that set are added to a new `ImmutableHashSet`.
+>
+> ```C#
+> var array = new[] { "One", "Two", "Two", "One", "Three" };
+> var set = new HashSet(array).ToImmutableHashSet();
+> ```
+
+## Using Builders
+- When creating an immutable collection with a lot of mutation, use a builder. Builders are optimized to populate the
+ internal storage of an immutable collection.
+- The following code achieves the expected result but inefficiently creates several intermediate `ImmutableList`
+ instances.
+
+```C#
+ImmutableList CreateList()
+{
+ var list = ImmutableList.Empty;
+ for (var i = 0; i < 10; i++)
+ {
+ list = list.Add(i);
+ }
+
+ return list;
+}
+```
+
+- The version below populates an `ImmutableList.Builder` and creates just a single `ImmutableList` instance
+ at the end.
+
+```C#
+ImmutableList CreateList()
+{
+ var builder = ImmutableList.CreateBuilder();
+
+ for (var i = 0; i < 10; i++)
+ {
+ builder.Add(i);
+ }
+
+ return builder.ToImmutable();
+}
+```
+
+## `ImmutableArray`
+- `ImmutableArray` is very different than the other immutable collections. It is the only struct collection type,
+ and is not optimized for persistence. (In hindsight, perhaps a more appropriate name would have been
+ `FrozenArray`?)
+- `ImmutableArray` is a relatively simple struct that provides read-only access to an internal array.
+
+> [!WARNING]
+> **Be aware of copies!**
+>
+> In order to maintain its immutability semantics, `ImmutableArray` *always* creates a copy of the array it is
+> wrapping internally. If it didn’t, external changes to the array would be reflected in the `ImmutableArray`.
+>
+> Because a new array copy is created for every `ImmutableArray` it is important to be mindful of chaining methods
+> that produce immutable arrays to avoid unnecessary intermediate array copies.
+>
+> In addition, as of System.Immutable.Collections 8.0.0, there is a new `ImmutableCollectionsMarshal` class that can
+> provide access to the internal array of an `ImmutableArray` or to create an new `ImmutableArray` that wraps an
+> existing array without copying. These can be used in high performance scenarios, but should be employed carefully to
+> avoid introducing subtle bugs.
+
+- Because `ImmutableArray` is a struct that wraps a single field of a reference type, it is essentially free to copy
+ at runtime. However, this also leaves a bit of a usability wart because, as a struct, an `ImmutableArray` reference
+ can never be null, but it can has its default, zeroed-out value where the internal array reference is null. For this
+ reason, an `IsDefault` property is provided to check if an `ImmutableArray` is actually wrapping an array.
+- `ImmutableArray` *can* be used as a persistent data structure via non-destructive mutation, but mutating methods
+ are generally implemented to copy the elements of the internal array. For example, `Add` will create a copy of the
+ internal array storage with an additional element and return it as an `ImmutableArray`.
+
+> [!NOTE]
+> **A Little History**
+>
+> `ImmutableArray` was not part of System.Collections.Immutable when originally conceived. It was developed out of
+> necessity by Roslyn to expose array data while avoiding the inherent problems of exposing an array. (At the time,
+> .NET arrays didn’t even implement `IReadOnlyList`, which didn’t ship until .NET Framework 4.5.)
+> System.Collections.Immutable itself was inspired by the many persistent data structures used internally by Roslyn and
+> was intended to be used within Visual Studio for asynchronous code. However, the NuGet package became so popular that
+> it was ultimately pulled into the .NET runtime.
+
+### Using `ImmutableArray.Builder`
+- The Builder type for `ImmutableArray` provides a couple of features not provided by other immutable collection
+ builders.
+- `ToImmutable()`: Like other builders, creates a new `ImmutableArray` that wraps a copy of the filled portion of
+ internal array buffer used by the builder.
+- `MoveToImmutable()`: Creates a new `ImmutableArray` that wraps the internal array buffer used by the builder. Note
+ that this requires that the builder’s capacity is the same as its count. In other words, the builder’s internal array
+ buffer must be completely filled, or this will throw an `InvalidOperationException`. If the operation is successful,
+ the internal buffer is set to an empty array.
+- `DrainToImmutable()`: This is sort of like a combination of `ToImmutable()` and `MoveToImmutable()`. This operation
+ “drains” the builder by checking if the capacity equals the count. If true, it returns a new `ImmutableArray` that
+ wraps the internal array buffer. If false, it returns a new `ImmutableArray` that wraps a copy of the filled
+ portion of the internal array buffer. In either case, the internal buffer is set to an empty array.
+
+> [!CAUTION]
+> **Immutable collections as static data**
+>
+> Because of their performance characteristics, most of the immutable collections are *not* suitable for static
+> collections. In fact, `ImmutableArray` is really the only immutable collection that should be used for static data,
+> since accessing it is essentially the same as accessing an array.
+>
+> When creating a static lookup table it can be tempting to reach for an `ImmutableHashSet` or an
+> `ImmutableDictionary`, but that temptation should be resisted! Lookup will always be slower than using
+> he imperative counterpart because of the internal tree structures employed for immutable collections.
+>
+> There are several tricks that can be used to encapsulate imperative collections as static data. For example, a nested
+> static class could hide a `HashSet` or `Dictionary` behind static methods that access the
+> collections. However, a better solution available today is to use a [frozen collection](#Frozen-Collections).
+
+## Frozen Collections
+- The System.Collections.Frozen namespace became available starting with version 8.0.0 of the
+ System.Collections.Immutable NuGet package.
+- Currently, there are two frozen collection types: `FrozenSet` and `FrozenDictionary`.
+- The frozen collections are not persistent; in fact, they can’t be mutated at all! Instead, frozen collections are
+ optimized for faster lookup operations — faster than their imperative counterparts.
+- Frozen collections provide faster lookup by performing up-front analysis and selecting an optimal implementation for
+ the content. This means that they are much more expensive to create.
+- Because of their higher creation cost and improved lookup performance, frozen collections are best suited for
+ static data.
+
+# Array Pools
+- When a temporary array is needed to perform work and the lifetime of the array is bounded, consider acquiring a
+ pooled array. `ArrayPool` can be used to acquire an array of some minimum length that can be returned to the pool
+ when the work is done.
+
+> [!WARNING]
+> **Be mindful of the array size!**
+>
+> The size of an array acquired from an `ArrayPool` is guaranteed to be at least as large as the minimum length that
+> was requested. However, it is likely that a larger array will have been returned. So, care should be taken to avoid
+> using the acquired array’s length, unless that’s what’s needed.
+
+- Razor provides a handful of helper extension methods that acquire pooled arrays and return them within the scope of a
+using statement:
+
+```C#
+var pool = ArrayPool.Shared;
+
+using (pool.GetPooledArray(minimumLength: 42, out var array)
+{
+ // When using array but be careful that array.Length >= minimumLength.
+}
+
+using (pool.GetPooledArraySpan(minimumLength: 42, out var span)
+{
+ // span is array.AsSpan(0, minimumLength) to help avoid subtle bugs.
+}
+```
+
+# Object Pools
+- Razor provides object pooling facilities based on
+ [Microsoft.Extensions.ObjectPool](https://www.nuget.org/packages/Microsoft.Extensions.ObjectPool/) (which was
+ originally based on Roslyn’s `ObjectPool`) along with several premade pools for many collection types in the
+ [Microsoft.AspNetCore.Razor.PooledObjects](https://github.com/dotnet/razor/tree/5c0677ad275e64300b897de0f6e8856ebe13f07b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects)
+ namespace. These can be used to acquire temporary collections to use for work and return when finished.
+
+```C#
+using var _ = ListPool.GetPooledObject(out var list);
+
+// Use list here. It'll be returned to the pool at the end of the using
+// statement's scope.
+```
+
+- Pooled collections provide a couple of benefits.
+ 1. Pooled collections decrease pressure on the garbage collector by reusing collection instances.
+ 2. Pooled collections avoid growing a collection’s internal storage. For example, when the `List` acquired from
+ `ListPool` in the code sample above is returned to the pool, it will be cleared. However, the capacity of its
+ internal storage will only be trimmed if it is larger than 512. So, lists acquired from the pool are likely to
+ already have a larger capacity than needed for most work.
+
+> [!WARNING]
+> **Don't allow pooled objects to escape their scope!**
+>
+> Consider the following code:
+>
+> ```C#
+> List M()
+> {
+> using var _ = ListPool.GetPooledObject(out var list);
+>
+> // use list...
+>
+> return list;
+> }
+> ```
+>
+> The compiler won't complain if a pooled `List` escapes its scope. In the code above, the `List` will be
+> returned to the pool at the end of the using statement's scope but is returned from the method. This results
+> several problems:
+>
+> 1. The list will be cleared when returned to the pool. So, the caller will find it to be empty.
+> 2. If the caller adds items to the list, other code acquiring a pooled list might receive the mutated list!
+> 3. Likewise, if the caller holds onto the list, other code acquiring a pooled list might receive the same list and
+> mutate it!
+>
+> In essence, a pooled object that escapes its scope can corrupt the pool in came from.
+
+# ✨It’s Magic! `PooledArrayBuilder`
+
+- Razor’s [`PooledArrayBuilder`](https://github.com/dotnet/razor/blob/5c0677ad275e64300b897de0f6e8856ebe13f07b/src/Shared/Microsoft.AspNetCore.Razor.Utilities.Shared/PooledObjects/PooledArrayBuilder%601.cs)
+ is heavily inspired by Roslyn’s [`TemporaryArray`](https://github.com/dotnet/roslyn/blob/d176f9b5a7220cd95a6d5811ba1c49ac392a2fdc/src/Compilers/Core/Portable/Collections/TemporaryArray%601.cs).
+- The important feature of this type (and the reason we’ve started using it all over Razor) is that it stores the first
+ 4 elements of the array being built inline as fields. After 4 elements have been added, it will acquire a pooled
+ `ImmutableArray.Builder`. This makes it extremely cheap to use for small arrays and reduces pressure on the object
+ pools.
+- Because `PooledArrayBuilder` is a struct, it must be passed by-reference. Otherwise, any elements added by a method
+ it’s passed to won’t be reflected back at the call-site.
+- To avoid writing buggy code that accidentally copies a `PooledArrayBuilder`, it is marked with a `[NonCopyable]`
+ attribute. A Roslyn analyzer tracks types decorated with that attribute and ensures that instances are never copied.
+- Because `PooledArrayBuilder` _may_ acquire a pooled `ImmutableArray.Builder`, it is disposable and should
+ generally be created within a using statement. However, that makes it a bit more awkward to pass by reference, so a
+ special `AsRef()` extension method is provided.
+- In the following code example, an `ImmutableArray.Builder` will never be acquired from the pool because the
+ `PooledArrayBuilder` only ever contains three elements.
+
+```C#
+ImmutableArray BuildStrings()
+{
+ using var builder = new PooledArrayBuilder();
+ AddElements(ref builder.AsRef());
+
+ return builder.DrainToImmutable();
+}
+
+void AddElements(ref PooledArrayBuilder builder)
+{
+ builder.Add("One");
+ builder.Add("Two");
+ builder.Add("Three");
+}
+```
+
+# Using LINQ
+- LINQ (that is, LINQ to Objects) is a bit of a tricky subject. It has been used extensively throughout Razor for a long
+ time. It’s certainly not off limits but should be used with an understanding of the hidden costs:
+ - Every lambda expression represents at least one allocation — the delegate that holds it.
+ - A lambda that accesses variables or instance data from an outer scope will result in a closure being allocated each
+ time the delegate is invoked.
+ - Many LINQ methods allocate an iterator instance.
+ - Because Razor tooling runs in Visual Studio, it runs on .NET Framework and doesn’t benefit from many LINQ
+ optimizations made in modern .NET.
+ - Because LINQ methods target `IEnumerable` instances, they can trigger additional allocations depending on how
+ `GetEnumerator()` is implemented. For example, a simple call like `Queue.Any()` might seem innocuous—it doesn’t
+ even have a lambda! However, the implementation of
+ [`Enumerable.Any()`](https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,1288) on .NET
+ Framework doesn’t have any fast paths and simply calls `GetEnumerator()`. So, `Any()` boxes `Queue`’s struct
+ enumerator, resulting an allocation every time it’s called. In a tight loop, that could be disastrous!
+ - LINQ can obfuscate algorithmic complexity. It can be hard to see that introducing a LINQ expression has made an
+ algorithm O(n^2).
+
+## Best Practices
+- Consider whether LINQ could have a negative performance impact for a particular scenario. Is this a hot path? Is it
+ happening in a loop?
+- Always try to use static lambdas to ensure closures aren’t created and delegates are cached and reused.
+- What collection type is being targeted? Do we have specialized LINQ methods that could be used? Razor provides a few
+ for `ImmutableArray` and `IReadOnlyList`.
+
+# Using Collection Expressions
+- C# 12 introduced collection expressions as a language-level abstraction to generate collection-based code. It is a
+ goal of collection expressions to produce efficient code.
+- Collection expressions are generally very good. They are especially helpful for combining collections or even query
+ expressions.
+
+```C#
+int[] Combine(List list, HashSet set)
+{
+ return [..list, ..set];
+}
+
+int[] Squares(List list, HashSet set)
+{
+ return [
+ ..from x in list select x * x,
+ ..from x in set select x * x
+ ];
+}
+```
+
+> [!WARNING]
+> **Considerations when using collection expressions**
+>
+> - Sometimes, a collection expression might create a new temporary collection instance, such as a `List`. However,
+> it will not acquire a temporary collection from Razor’s object pools ([SharpLab](https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0ATEBqAPgAQAYACfARhQG4BYAKHwGZSAmYgYWIG87jfSmAlgDsALgG0AusQCyACnIMAPMJEA+YgGcYARwCuMIWBgBKLjz4X8AdmJiAdHc079hmBJq0LAXzpegA=)).
+> - There are pathological collection expressions to be avoided. For example, never use a collection expression to
+> replace a call to `ImmutableArray.Builder.ToImmutable()` ([SharpLab](https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0ATEBqAPgAQAYACfARgDoBhCAG1pjABcBLCAOwGcKBJAWz4BXJgENgDANwBYAFD4AzKQBMxKsQDes4ttKL+Q0eJgBBKFBEBPADwt2TAHzEAsgApbTANoBdYiLOWASg0tHVCANz9iYEEWWgwYKGIAXmJ9YTEGU3MLalgRJhgAIRi4hJs7excA6RlQ0OjY+KgKYwwMACURdgBzGBc/bOqQuuJhuvwAdmIPCgookqavGtCAX1kVoA=)).
+> When using a collection expression in a new scenario or with an uncommon type, it's a good idea to try it out on
+> https://sharplab.io first.
+
+- Empty collection expression generally produces very efficient code and can be used without concern ([SharpLab](https://sharplab.io/#v2:EYLgtghglgdgPgAQEwEYCwAoBAGABAlAOgGEB7AG3IFMBjAFylJgGcBuTHfFAFnazwIkK1eoxaEAkmDABXOhGDU+nQQBlYAR2UCiAJRkwGYKkLAAHKNQBOAZSpWAblBpU2mDgGZ8SXMVwBvTFxg/C8EblwAWQAKAEoAoJCkgDkUaIBRGBljKwVqQnTzOgBPAB5YOgA+ONi+JJS0gEErXOKCorKK6tjaxPrcVOiAbQBdXox+4OSkYbG6yeSPWfGkgF8+3A2EMIjBgg9yw0rcZioNGSoYF3jAiZD1u+CtnYGZqVl5RSpm1sOq3AgLQgxRuGweSWe+F2S2IMmYdFIYF0VAgABMAPIwcjFdTw3DkKDw0GPXAPB6YIZkSi0BhMABCMksqPs0RKZiopAAZtFYfDEci0Zjsbi6LEADS4ABExCsKLoVElsRGnhOKOoqO8vjhCKRKIxWJxhLo0TMgIgYGYuAF+uxNlNMD+xwcEHIF2Y8RAuAk1qFhvhjswtySZisUGd8twsrRTGxuAqo1wAH1na7XLgALy4FNuwgAFVIP2BcT4kIquDoAAtCUMy7BmQAPEYZ47Jl1umswBsjebBbZxwy+UgGOjNpPZ1yEVSXADmlZLJL7Eky2XsEARVkduAA4lQ6MucmvSFY4hsg5NOUeUTQK7hos6rFm21R+2On+6Nkkz5MQgQUPgAOyPqmPb1OC9zuCSS5ZAe65cB4hA7nu0GruuJ4kkk6bHIh+4oUexYQUkfYEAAbFqfK6oKBoir4UbytEPoGnaEAOl0Jz2rEH4hJhuAwFQADu0TMOxfCrEAA=)).
+- It is expected that collection expressions will improve over time. At the time of writing, there are
+ [several open issues](https://github.com/dotnet/roslyn/issues?q=is%3Aissue+is%3Aopen+%22collection+expression%22+label%3AArea-Compilers+label%3A%22Code+Gen+Quality%22)
+ tracking collection expression enhancements.
+
+# Meta Tips
+
+- Always be aware of the memory layout, features, and performance characteristics of the data structure you are using.
+- If you have an implementation question for a .NET collection type, check out the source code using the
+ [.NET Source Browser](https://source.dot.net/) for modern .NET, or the
+ [.NET Framework Reference Source](https://referencesource.microsoft.com/). And of course, the .NET runtime repo is
+ available at [dotnet/runtime](https://github.com/dotnet/runtime).
+- Several reflection-based tools exist for exploring .NET assemblies, such as
+ [ILSpy](https://github.com/icsharpcode/ILSpy) or dotPeek (from JetBrains).
+- Use https://sharplab.io to see how code will be compiled. This can be especially useful for collection expressions,
+ which are usually very efficient do have pathological cases to avoid.
\ No newline at end of file
diff --git a/docs/Compiler Breaking Changes - DotNet 8.md b/docs/Compiler Breaking Changes - DotNet 8.md
new file mode 100644
index 00000000000..c2c31f9bcf3
--- /dev/null
+++ b/docs/Compiler Breaking Changes - DotNet 8.md
@@ -0,0 +1,76 @@
+# This document lists known breaking changes in Razor after .NET 8 all the way to .NET 9.
+
+## Parsing of `@` identifiers was unified
+
+***Introduced in VS 17.10 and .NET 8.0.300***
+
+In https://github.com/dotnet/razor/pull/10232, we adjusted the behavior of how an identifier is parsed following an `@` to be more consistent across Razor.
+This resulted in a few scenarios that have different behavior, listed below.
+
+### Verbatim interpolated strings
+
+Strings of the form `@$"ticket-{i}.png"` are no longer recognized. This will be fixed in a later release by changing to a new lexer; until then, use `$@` to work around the issue.
+
+### C# preprocessor directives followed by HTML are not parsed correctly
+
+1. The preprocessor directive is directly before HTML. This flavor looks something like this:
+```razor
+@{
+ #region R
+
@ViewData["Title"]
+ #endregion
+}
+```
+2. There is valid C# between the preprocessor directive and the html, but it doesn't have a character that tells the parser to end parsing before the HTML. This is a variation of 1, and can occur with things like `switch` statements:
+```razor
+@{
+ switch (true)
+ {
+ #region R
+ case true:
+
@(1 + 1)
+ break;
+ }
+}
+```
+
+Previously, C# preprocessor directives followed by HTML would sometimes be parsed correctly if the HTML had an `@` transition in it. It is now consistently parsed
+incorrectly. This will be resolved in a later release by changing to a new lexer. Until then, there are available workarounds to get this to compile.
+
+#### Surround the HTML in a block
+
+The HTML can be surrounded with braces.
+
+```razor
+@{
+ #if DEBUG
+ {
+
@ViewData["Title"]
+ }
+ #endif
+}
+```
+
+#### Add a semicolon to the directive
+
+Directives such as `#region` and `#endregion` allow putting a semicolon after the directive. This will effectively work around the issue.
+
+```razor
+@{
+ #region R ;
+
@ViewData["Title"]
+ #endregion
+}
+```
+
+#### Add a semicolon after the directive
+
+Directives such as `#if` and `#endif` do not allow semicolons after the directive condition, but one can be placed on the next line to make an empty statement.
+
+```razor
+@{
+ #if DEBUG
+ ;
+
@ViewData["Title"]
+ #endif
+}
diff --git a/docs/Parsing.md b/docs/Parsing.md
index a5208c9e525..ead3c502d21 100644
--- a/docs/Parsing.md
+++ b/docs/Parsing.md
@@ -58,4 +58,6 @@ CSharpCode
Literal: ^^^\r\n
```
-In this way we keep the whitespace as belonging to the overall CSharpCode node, but don't make it part of the directive itself, ensuring the editor sees the correct length for the directive.
\ No newline at end of file
+In this way we keep the whitespace as belonging to the overall CSharpCode node, but don't make it part of the directive itself, ensuring the editor sees the correct length for the directive.
+
+We apply a very similar fix to `@using` directives, to ensure that the newline is treated as metacode of the overall block, rather than being a part of the `using` itself.
\ No newline at end of file
diff --git a/docs/ProjectsAndLayering.md b/docs/ProjectsAndLayering.md
index 29c85730d64..e95f1b8efbe 100644
--- a/docs/ProjectsAndLayering.md
+++ b/docs/ProjectsAndLayering.md
@@ -119,7 +119,7 @@ target the broadest set of frameworks.
- Microsoft.AspNetCore.Razor.Test.MvcShim (`net8.0`;`net472`)
- Microsoft.AspNetCore.Razor.Test.MvcShim.ClassLib (`netstandard2.0`)
- Microsoft.AspNetCore.Razor.Test.MvcShim.Version1_X (`net8.0`;`net472`)
-- Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X (`net8.0`;`net4720`)
+- Microsoft.AspNetCore.Razor.Test.MvcShim.Version2_X (`net8.0`;`net472`)
### Tooling Core Tests
diff --git a/docs/contributing/Roslyn-Debugging.md b/docs/contributing/Roslyn-Debugging.md
index a3cd1492461..e316428ac12 100644
--- a/docs/contributing/Roslyn-Debugging.md
+++ b/docs/contributing/Roslyn-Debugging.md
@@ -8,18 +8,24 @@ Sometimes it may be necessary to make changes in [`dotnet/roslyn`](https://githu
2. `./Restore.cmd`
3. Make the desired changes in `dotnet/roslyn`.
4. `./Build.cmd -pack`. The `-pack` option causes the creation of NuGet packages.
-5. You should see the generated packages in the `\artifacts\packages\Debug\Debug` directory. Take note of the package versions (ie. `Microsoft.CodeAnalysis.Workspaces.Common.3.8.0-dev.nupkg` => `3.8.0-dev`).
-6. Open `NuGet.config` and add the local package source `` and package source below under the `packageSourceMapping` tag:
+5. You should see the generated packages in the `\artifacts\packages\Debug` directory. Take note of the package versions (ie. `Microsoft.CodeAnalysis.Workspaces.Common.3.8.0-dev.nupkg` => `3.8.0-dev`).
+6. In the Razor repo, open `NuGet.config` and add two local package sources:
+ * ``
+ * ``
+7. Add the package source mappings below under the `packageSourceMapping` tag:
```xml
-
+
+
+
+
-
```
-7. Open `eng/Versions.props` and update `RoslynPackageVersion` to the version noted in step 5.
-8. To get the end-to-end local debugging working, running `./Build.cmd -deploy` script from roslyn repository. this will copy over the right binaries from roslyn to the shared local roslyn/razor hive.
+7. Open `eng/Versions.props` and find the `MicrosoftCodeAnalysisExternalAccessRazorPackageVersion` property.
+8. Grab the value of that property, and replace all instances of that value in the file to be the version noted in step 5.
+9. To get the end-to-end local debugging working, running `./Build.cmd -deployExtensions` script from roslyn repository. this will copy over the right binaries from roslyn to the shared local roslyn/razor hive.
## Troubleshooting
diff --git a/eng/AfterSigning.targets b/eng/AfterSigning.targets
index e334d9498ec..68095f7bcf0 100644
--- a/eng/AfterSigning.targets
+++ b/eng/AfterSigning.targets
@@ -1,6 +1,6 @@
-
+ $(ArtifactsDir)VSSetup\Microsoft.VisualStudio.RazorExtension.vsix
@@ -27,7 +27,7 @@
AfterTargets="GenerateVisualStudioInsertionManifests"
Inputs="$(_RazorAssemblyVersion)"
Outputs="$(_DependentAssemblyVersionsFile)"
- Condition="'$(OS)'=='WINDOWS_NT' AND '$(ArcadeBuildFromSource)' != 'true'">
+ Condition="'$(OS)'=='WINDOWS_NT' AND '$(DotNetBuildSourceOnly)' != 'true'">
<_AssemblyVersionEntry Include="RazorRuntimeAssembly" />
<_AssemblyVersionEntry Include="RazorToolingAssembly" />
diff --git a/eng/SourceBuild.props b/eng/DotNetBuild.props
similarity index 86%
rename from eng/SourceBuild.props
rename to eng/DotNetBuild.props
index 7c3d9e2731d..d06a5255433 100644
--- a/eng/SourceBuild.props
+++ b/eng/DotNetBuild.props
@@ -1,4 +1,4 @@
-
+
diff --git a/eng/Publishing.props b/eng/Publishing.props
index 3df1479c419..9344f044ddc 100644
--- a/eng/Publishing.props
+++ b/eng/Publishing.props
@@ -27,7 +27,7 @@
-
+ false
diff --git a/eng/SourceBuildPrebuiltBaseline.xml b/eng/SourceBuildPrebuiltBaseline.xml
index 4f2766f12ec..5c7ee51b9cd 100644
--- a/eng/SourceBuildPrebuiltBaseline.xml
+++ b/eng/SourceBuildPrebuiltBaseline.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/eng/TSAConfig.gdntsa b/eng/TSAConfig.gdntsa
index d2035a27979..d8d1c1cdc11 100644
--- a/eng/TSAConfig.gdntsa
+++ b/eng/TSAConfig.gdntsa
@@ -11,8 +11,5 @@
"projectName": "DevDiv",
"areaPath": "DevDiv\\NET Developer Experience\\Razor Tooling",
"iterationPath": "DevDiv",
- "tools": [
- "APIScan",
- "BinSkim"
- ]
+ "allTools": true
}
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 7ea417466f4..2df6540542f 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -6,87 +6,87 @@
839cdfb0ecca5e0be3dbccd926e7651ef50fdf10
-
+ https://github.com/dotnet/source-build-reference-packages
- ad3c9aa85596f42c6a483233c50fab8cee8c412a
+ 4660d88cf953fbbd14192c787053a20246ce1aeb
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
-
+ https://github.com/dotnet/roslyn
- 9f86520c46f67d2a8a59af189f8fd87e35c574bb
+ 7b7951aa13c50ad768538e58ed3805898b058928
@@ -96,14 +96,14 @@
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime3a25a7f1cc446b60678ed25c9d829420d6321eba
-
+ https://github.com/dotnet/arcade
- dd332f2d4e21daa8b79f84251ab156af9a0b11b2
+ 3c393bbd85ae16ddddba20d0b75035b0c6f1a52d
-
+ https://github.com/dotnet/arcade
- dd332f2d4e21daa8b79f84251ab156af9a0b11b2
+ 3c393bbd85ae16ddddba20d0b75035b0c6f1a52d
diff --git a/eng/Versions.props b/eng/Versions.props
index 707ebbb49ad..f8a2092014e 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -30,8 +30,8 @@
imported. This OK because we want to just have an obvious salt for a local build.
-->
- 17.12.3
- 17.12
+ 17.13.1
+ 17.13$(AddinMajorVersion)$(AddinVersion).$(OfficialBuildId)$(AddinVersion).42424242.42
@@ -49,29 +49,29 @@
6.0.2-servicing.22064.66.0.1
- 10.0.0-alpha.1.24455.1
- 9.0.0-beta.24453.1
+ 10.0.0-alpha.1.24515.1
+ 9.0.0-beta.24516.21.0.0-beta.23475.11.0.0-beta.23475.1
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
- 4.12.0-3.24454.5
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
+ 4.12.0-3.24466.4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- View component '{0}' must have exactly one public method named '{1}' or '{2}'.
-
-
- Method '{0}' of view component '{1}' should be declared to return {2}<T>.
-
-
- Could not find an '{0}' or '{1}' method for the view component '{2}'.
-
-
- Method '{0}' of view component '{1}' cannot return a {2}.
-
-
- Method '{0}' of view component '{1}' should be declared to return a value.
-
-
\ No newline at end of file
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperConventions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperConventions.cs
deleted file mode 100644
index 058c20868e3..00000000000
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperConventions.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#nullable disable
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X;
-
-public static class ViewComponentTagHelperConventions
-{
- public static readonly string Kind = "MVC.ViewComponent";
-}
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperIntermediateNode.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperIntermediateNode.cs
deleted file mode 100644
index 5f08ef6be68..00000000000
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperIntermediateNode.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#nullable disable
-
-using System;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
-using Microsoft.AspNetCore.Razor.Language.Intermediate;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X;
-
-public sealed class ViewComponentTagHelperIntermediateNode : ExtensionIntermediateNode
-{
- public override IntermediateNodeCollection Children { get; } = IntermediateNodeCollection.ReadOnly;
-
- public string ClassName { get; set; }
-
- public TagHelperDescriptor TagHelper { get; set; }
-
- public override void Accept(IntermediateNodeVisitor visitor)
- {
- if (visitor == null)
- {
- throw new ArgumentNullException(nameof(visitor));
- }
-
- AcceptExtensionNode(this, visitor);
- }
-
- public override void WriteNode(CodeTarget target, CodeRenderingContext context)
- {
- if (target == null)
- {
- throw new ArgumentNullException(nameof(target));
- }
-
- if (context == null)
- {
- throw new ArgumentNullException(nameof(context));
- }
-
- var extension = target.GetExtension();
- if (extension == null)
- {
- ReportMissingCodeTargetExtension(context);
- return;
- }
-
- extension.WriteViewComponentTagHelper(context, this);
- }
-
- public override void FormatNode(IntermediateNodeFormatter formatter)
- {
- formatter.WriteContent(ClassName);
-
- formatter.WriteProperty(nameof(ClassName), ClassName);
- formatter.WriteProperty(nameof(TagHelper), TagHelper?.DisplayName);
- }
-}
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperMetadata.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperMetadata.cs
deleted file mode 100644
index 88d92b8cc7b..00000000000
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperMetadata.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#nullable disable
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X;
-
-public static class ViewComponentTagHelperMetadata
-{
- ///
- /// The key in a containing
- /// the short name of a view component.
- ///
- public static readonly string Name = "MVC.ViewComponent.Name";
-}
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperPass.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperPass.cs
deleted file mode 100644
index cbacadea315..00000000000
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperPass.cs
+++ /dev/null
@@ -1,205 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#nullable disable
-
-using System.Collections.Generic;
-using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.AspNetCore.Razor.Language.Extensions;
-using Microsoft.AspNetCore.Razor.Language.Intermediate;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X;
-
-public class ViewComponentTagHelperPass : IntermediateNodePassBase, IRazorOptimizationPass
-{
- // Run after the default taghelper pass
- public override int Order => IntermediateNodePassBase.DefaultFeatureOrder + 2000;
-
- protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
- {
- var @namespace = documentNode.FindPrimaryNamespace();
- var @class = documentNode.FindPrimaryClass();
- if (@namespace == null || @class == null)
- {
- // Nothing to do, bail. We can't function without the standard structure.
- return;
- }
-
- var context = new Context(@namespace, @class);
-
- // For each VCTH *usage* we need to rewrite the tag helper node to use the tag helper runtime to construct
- // and set properties on the the correct field, and using the name of the type we will generate.
- var nodes = documentNode.FindDescendantNodes();
- for (var i = 0; i < nodes.Count; i++)
- {
- var node = nodes[i];
- foreach (var tagHelper in node.TagHelpers)
- {
- RewriteUsage(context, node, tagHelper);
- }
- }
-
- // Then for each VCTH *definition* that we've seen we need to generate the class that implements
- // ITagHelper and the field that will hold it.
- foreach (var tagHelper in context.TagHelpers)
- {
- AddField(context, tagHelper);
- AddTagHelperClass(context, tagHelper);
- }
- }
-
- private void RewriteUsage(Context context, TagHelperIntermediateNode node, TagHelperDescriptor tagHelper)
- {
- if (!tagHelper.IsViewComponentKind())
- {
- return;
- }
-
- context.Add(tagHelper);
-
- // Now we need to insert a create node using the default tag helper runtime. This is similar to
- // code in DefaultTagHelperOptimizationPass.
- //
- // Find the body node.
- var i = 0;
- while (i < node.Children.Count && node.Children[i] is TagHelperBodyIntermediateNode)
- {
- i++;
- }
- while (i < node.Children.Count && node.Children[i] is DefaultTagHelperBodyIntermediateNode)
- {
- i++;
- }
-
- // Now find the last create node.
- while (i < node.Children.Count && node.Children[i] is DefaultTagHelperCreateIntermediateNode)
- {
- i++;
- }
-
- // Now i has the right insertion point.
- node.Children.Insert(i, new DefaultTagHelperCreateIntermediateNode()
- {
- FieldName = context.GetFieldName(tagHelper),
- TagHelper = tagHelper,
- TypeName = context.GetFullyQualifiedName(tagHelper),
- });
-
- // Now we need to rewrite any set property nodes to use the default runtime.
- for (i = 0; i < node.Children.Count; i++)
- {
- if (node.Children[i] is TagHelperPropertyIntermediateNode propertyNode &&
- propertyNode.TagHelper == tagHelper)
- {
- // This is a set property for this VCTH - we need to replace it with a node
- // that will use our field and property name.
- node.Children[i] = new DefaultTagHelperPropertyIntermediateNode(propertyNode)
- {
- FieldName = context.GetFieldName(tagHelper),
- PropertyName = propertyNode.BoundAttribute.GetPropertyName(),
- };
- }
- }
- }
-
- private void AddField(Context context, TagHelperDescriptor tagHelper)
- {
- // We need to insert a node for the field that will hold the tag helper. We've already generated a field name
- // at this time and use it for all uses of the same tag helper type.
- //
- // We also want to preserve the ordering of the nodes for testability. So insert at the end of any existing
- // field nodes.
- var i = 0;
- while (i < context.Class.Children.Count && context.Class.Children[i] is DefaultTagHelperRuntimeIntermediateNode)
- {
- i++;
- }
-
- while (i < context.Class.Children.Count && context.Class.Children[i] is FieldDeclarationIntermediateNode)
- {
- i++;
- }
-
- context.Class.Children.Insert(i, new FieldDeclarationIntermediateNode()
- {
- Annotations =
- {
- { CommonAnnotations.DefaultTagHelperExtension.TagHelperField, bool.TrueString },
- },
- Modifiers =
- {
- "private",
- },
- FieldName = context.GetFieldName(tagHelper),
- FieldType = "global::" + context.GetFullyQualifiedName(tagHelper),
- });
- }
-
- private void AddTagHelperClass(Context context, TagHelperDescriptor tagHelper)
- {
- var node = new ViewComponentTagHelperIntermediateNode()
- {
- ClassName = context.GetClassName(tagHelper),
- TagHelper = tagHelper
- };
-
- context.Class.Children.Add(node);
- }
-
- private struct Context
- {
- private readonly Dictionary _tagHelpers;
-
- public Context(NamespaceDeclarationIntermediateNode @namespace, ClassDeclarationIntermediateNode @class)
- {
- Namespace = @namespace;
- Class = @class;
-
- _tagHelpers = new Dictionary();
- }
-
- public ClassDeclarationIntermediateNode Class { get; }
-
- public NamespaceDeclarationIntermediateNode Namespace { get; }
-
-
- public IEnumerable TagHelpers => _tagHelpers.Keys;
-
- public bool Add(TagHelperDescriptor tagHelper)
- {
- if (_tagHelpers.ContainsKey(tagHelper))
- {
- return false;
- }
-
- var className = $"__Generated__{tagHelper.GetViewComponentName()}ViewComponentTagHelper";
- var namespaceSeparator = string.IsNullOrEmpty(Namespace.Content) ? string.Empty : ".";
- var fullyQualifiedName = $"{Namespace.Content}{namespaceSeparator}{Class.ClassName}.{className}";
- var fieldName = GenerateFieldName(tagHelper);
-
- _tagHelpers.Add(tagHelper, (className, fullyQualifiedName, fieldName));
-
- return true;
- }
-
- public string GetClassName(TagHelperDescriptor taghelper)
- {
- return _tagHelpers[taghelper].className;
- }
-
- public string GetFullyQualifiedName(TagHelperDescriptor taghelper)
- {
- return _tagHelpers[taghelper].fullyQualifiedName;
- }
-
- public string GetFieldName(TagHelperDescriptor taghelper)
- {
- return _tagHelpers[taghelper].fieldName;
- }
-
- private static string GenerateFieldName(TagHelperDescriptor tagHelper)
- {
- return $"__{tagHelper.GetViewComponentName()}ViewComponentTagHelper";
- }
- }
-}
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperTargetExtension.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperTargetExtension.cs
index 8d63ca7aa11..3d8f4117fdd 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperTargetExtension.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTagHelperTargetExtension.cs
@@ -9,6 +9,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
+using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X;
@@ -65,7 +66,7 @@ public void WriteViewComponentTagHelper(CodeRenderingContext context, ViewCompon
using (context.CodeWriter.BuildClassDeclaration(
PublicModifiers,
node.ClassName,
- TagHelperTypeName,
+ new BaseTypeWithModel(TagHelperTypeName),
interfaces: null,
typeParameters: null,
context))
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTypeVisitor.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTypeVisitor.cs
deleted file mode 100644
index 7e2b8240fb5..00000000000
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTypeVisitor.cs
+++ /dev/null
@@ -1,88 +0,0 @@
-// 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.Generic;
-using Microsoft.CodeAnalysis;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X;
-
-internal sealed class ViewComponentTypeVisitor : SymbolVisitor
-{
- private readonly INamedTypeSymbol _viewComponentAttribute;
- private readonly INamedTypeSymbol? _nonViewComponentAttribute;
- private readonly List _results;
-
- public ViewComponentTypeVisitor(
- INamedTypeSymbol viewComponentAttribute,
- INamedTypeSymbol? nonViewComponentAttribute,
- List results)
- {
- _viewComponentAttribute = viewComponentAttribute;
- _nonViewComponentAttribute = nonViewComponentAttribute;
- _results = results;
- }
-
- public override void VisitNamedType(INamedTypeSymbol symbol)
- {
- if (IsViewComponent(symbol))
- {
- _results.Add(symbol);
- }
-
- if (symbol.DeclaredAccessibility != Accessibility.Public)
- {
- return;
- }
-
- foreach (var member in symbol.GetTypeMembers())
- {
- Visit(member);
- }
- }
-
- public override void VisitNamespace(INamespaceSymbol symbol)
- {
- foreach (var member in symbol.GetMembers())
- {
- Visit(member);
- }
- }
-
- internal bool IsViewComponent(INamedTypeSymbol symbol)
- {
- if (_viewComponentAttribute == null)
- {
- return false;
- }
-
- if (symbol.DeclaredAccessibility != Accessibility.Public ||
- symbol.IsAbstract ||
- symbol.IsGenericType ||
- AttributeIsDefined(symbol, _nonViewComponentAttribute))
- {
- return false;
- }
-
- return symbol.Name.EndsWith(ViewComponentTypes.ViewComponentSuffix, StringComparison.Ordinal) ||
- AttributeIsDefined(symbol, _viewComponentAttribute);
- }
-
- private static bool AttributeIsDefined(INamedTypeSymbol? type, INamedTypeSymbol? queryAttribute)
- {
- if (type == null || queryAttribute == null)
- {
- return false;
- }
-
- foreach (var attribute in type.GetAttributes())
- {
- if (SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, queryAttribute))
- {
- return true;
- }
- }
-
- return AttributeIsDefined(type.BaseType, queryAttribute);
- }
-}
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTypes.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTypes.cs
deleted file mode 100644
index c333ca62aee..00000000000
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc.Version2_X/ViewComponentTypes.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#nullable disable
-
-using System;
-
-namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X;
-
-internal static class ViewComponentTypes
-{
- public const string Assembly = "Microsoft.AspNetCore.Mvc.ViewFeatures";
-
- public static readonly Version AssemblyVersion = new Version(1, 1, 0, 0);
-
- public const string ViewComponentSuffix = "ViewComponent";
-
- public const string ViewComponentAttribute = "Microsoft.AspNetCore.Mvc.ViewComponentAttribute";
-
- public const string NonViewComponentAttribute = "Microsoft.AspNetCore.Mvc.NonViewComponentAttribute";
-
- public const string GenericTask = "System.Threading.Tasks.Task`1";
-
- public const string Task = "System.Threading.Tasks.Task";
-
- public const string IDictionary = "System.Collections.Generic.IDictionary`2";
-
- public const string AsyncMethodName = "InvokeAsync";
-
- public const string SyncMethodName = "Invoke";
-
- public static class ViewComponent
- {
- public const string Name = "Name";
- }
-}
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/InjectDirective.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/InjectDirective.cs
index 15ed4fc0327..583286b24dc 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/InjectDirective.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/InjectDirective.cs
@@ -27,7 +27,7 @@ public static class InjectDirective
builder.Description = RazorExtensionsResources.InjectDirective_Description;
});
- public static RazorProjectEngineBuilder Register(RazorProjectEngineBuilder builder)
+ public static RazorProjectEngineBuilder Register(RazorProjectEngineBuilder builder, bool considerNullabilityEnforcement)
{
if (builder == null)
{
@@ -36,7 +36,7 @@ public static RazorProjectEngineBuilder Register(RazorProjectEngineBuilder build
builder.AddDirective(Directive);
builder.Features.Add(new Pass());
- builder.AddTargetExtension(new InjectTargetExtension());
+ builder.AddTargetExtension(new InjectTargetExtension(considerNullabilityEnforcement));
return builder;
}
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/InjectTargetExtension.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/InjectTargetExtension.cs
index 46e83e4cae9..0ea1c5ac9b0 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/InjectTargetExtension.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/InjectTargetExtension.cs
@@ -9,7 +9,7 @@
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions;
-public class InjectTargetExtension : IInjectTargetExtension
+public class InjectTargetExtension(bool considerNullabilityEnforcement) : IInjectTargetExtension
{
private const string RazorInjectAttribute = "[global::Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute]";
@@ -42,7 +42,7 @@ public void WriteInjectProperty(CodeRenderingContext context, InjectIntermediate
else if (!node.IsMalformed)
{
var property = $"public {node.TypeName} {node.MemberName} {{ get; private set; }}";
- if (!context.Options.SuppressNullabilityEnforcement)
+ if (considerNullabilityEnforcement && !context.Options.SuppressNullabilityEnforcement)
{
property += " = default!;";
}
@@ -61,7 +61,7 @@ public void WriteInjectProperty(CodeRenderingContext context, InjectIntermediate
void WriteProperty()
{
- if (!context.Options.SuppressNullabilityEnforcement)
+ if (considerNullabilityEnforcement && !context.Options.SuppressNullabilityEnforcement)
{
context.CodeWriter.WriteLine("#nullable restore");
}
@@ -70,7 +70,7 @@ void WriteProperty()
.WriteLine(RazorInjectAttribute)
.WriteLine(property);
- if (!context.Options.SuppressNullabilityEnforcement)
+ if (considerNullabilityEnforcement && !context.Options.SuppressNullabilityEnforcement)
{
context.CodeWriter.WriteLine("#nullable disable");
}
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/ModelDirective.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/ModelDirective.cs
index 8d8e6338ea4..206d2d7efc0 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/ModelDirective.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/ModelDirective.cs
@@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language;
+using Microsoft.AspNetCore.Razor.Language.Extensions;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions;
@@ -43,10 +44,10 @@ public static string GetModelType(DocumentIntermediateNode document)
}
var visitor = new Visitor();
- return GetModelType(document, visitor);
+ return GetModelType(document, visitor).Content;
}
- private static string GetModelType(DocumentIntermediateNode document, Visitor visitor)
+ private static IntermediateToken GetModelType(DocumentIntermediateNode document, Visitor visitor)
{
visitor.Visit(document);
@@ -57,17 +58,17 @@ private static string GetModelType(DocumentIntermediateNode document, Visitor vi
var tokens = directive.Tokens.ToArray();
if (tokens.Length >= 1)
{
- return tokens[0].Content;
+ return IntermediateToken.CreateCSharpToken(tokens[0].Content, tokens[0].Source);
}
}
if (document.DocumentKind == RazorPageDocumentClassifierPass.RazorPageDocumentKind)
{
- return visitor.Class.ClassName;
+ return IntermediateToken.CreateCSharpToken(visitor.Class.ClassName);
}
else
{
- return "dynamic";
+ return IntermediateToken.CreateCSharpToken("dynamic");
}
}
@@ -99,10 +100,13 @@ protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentInte
};
visitor.Namespace?.Children.Insert(0, usingNode);
+ modelType.Source = null;
}
- var baseType = visitor.Class?.BaseType?.Replace("", "<" + modelType + ">");
- visitor.Class.BaseType = baseType;
+ if (visitor.Class?.BaseType is BaseTypeWithModel { ModelType: not null } existingBaseType)
+ {
+ existingBaseType.ModelType = modelType;
+ }
}
}
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/MvcViewDocumentClassifierPass.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/MvcViewDocumentClassifierPass.cs
index 4ddbe268963..fd80aa0b4ff 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/MvcViewDocumentClassifierPass.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/MvcViewDocumentClassifierPass.cs
@@ -4,6 +4,7 @@
#nullable disable
using Microsoft.AspNetCore.Razor.Language;
+using Microsoft.AspNetCore.Razor.Language.Extensions;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions;
@@ -53,7 +54,7 @@ protected override void OnDocumentStructureCreated(
{
@class.ClassName = className;
}
- @class.BaseType = "global::Microsoft.AspNetCore.Mvc.Razor.RazorPage";
+ @class.BaseType = new BaseTypeWithModel("global::Microsoft.AspNetCore.Mvc.Razor.RazorPage", location: null);
@class.Modifiers.Clear();
if (_useConsolidatedMvcViews)
{
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/RazorExtensions.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/RazorExtensions.cs
index fa19e49ba40..317a5f387b0 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/RazorExtensions.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/RazorExtensions.cs
@@ -22,7 +22,7 @@ public static void Register(RazorProjectEngineBuilder builder)
throw new ArgumentNullException(nameof(builder));
}
- InjectDirective.Register(builder);
+ InjectDirective.Register(builder, considerNullabilityEnforcement: true);
ModelDirective.Register(builder);
PageDirective.Register(builder);
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/RazorPageDocumentClassifierPass.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/RazorPageDocumentClassifierPass.cs
index 1706d408e53..0cab4df6007 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/RazorPageDocumentClassifierPass.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/RazorPageDocumentClassifierPass.cs
@@ -79,7 +79,7 @@ protected override void OnDocumentStructureCreated(
@class.ClassName = className;
}
- @class.BaseType = "global::Microsoft.AspNetCore.Mvc.RazorPages.Page";
+ @class.BaseType = new BaseTypeWithModel("global::Microsoft.AspNetCore.Mvc.RazorPages.Page");
@class.Modifiers.Clear();
if (_useConsolidatedMvcViews)
{
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/ViewComponentTagHelperTargetExtension.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/ViewComponentTagHelperTargetExtension.cs
index f8c3e34e3c7..212bdd87437 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/ViewComponentTagHelperTargetExtension.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Mvc/ViewComponentTagHelperTargetExtension.cs
@@ -8,6 +8,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
+using Microsoft.AspNetCore.Razor.Language.Intermediate;
namespace Microsoft.AspNetCore.Mvc.Razor.Extensions;
@@ -68,7 +69,7 @@ public void WriteViewComponentTagHelper(CodeRenderingContext context, ViewCompon
using (context.CodeWriter.BuildClassDeclaration(
PublicModifiers,
node.ClassName,
- TagHelperTypeName,
+ new BaseTypeWithModel(TagHelperTypeName),
interfaces: null,
typeParameters: null,
context))
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.Helpers.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.Helpers.cs
index e7399de064b..29c72c13cf4 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.Helpers.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.Helpers.cs
@@ -87,8 +87,7 @@ private static StaticCompilationTagHelperFeature GetStaticTagHelperFeature(Compi
private static SourceGeneratorProjectEngine GetGenerationProjectEngine(
SourceGeneratorProjectItem item,
IEnumerable imports,
- RazorSourceGenerationOptions razorSourceGeneratorOptions,
- bool isAddComponentParameterAvailable)
+ RazorSourceGenerationOptions razorSourceGeneratorOptions)
{
var fileSystem = new VirtualRazorProjectFileSystem();
fileSystem.Add(item);
@@ -107,7 +106,7 @@ private static SourceGeneratorProjectEngine GetGenerationProjectEngine(
options.SuppressMetadataSourceChecksumAttributes = !razorSourceGeneratorOptions.GenerateMetadataSourceChecksumAttributes;
options.SupportLocalizedComponentNames = razorSourceGeneratorOptions.SupportLocalizedComponentNames;
options.SuppressUniqueIds = razorSourceGeneratorOptions.TestSuppressUniqueIds;
- options.SuppressAddComponentParameter = !isAddComponentParameterAvailable;
+ options.SuppressAddComponentParameter = razorSourceGeneratorOptions.Configuration.SuppressAddComponentParameter;
}));
b.Features.Add(new ConfigureRazorParserOptions(razorSourceGeneratorOptions.UseRoslynTokenizer, razorSourceGeneratorOptions.CSharpParseOptions));
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.RazorProviders.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.RazorProviders.cs
index 6f1cfa303b4..73d6a8a0b4e 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.RazorProviders.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.RazorProviders.cs
@@ -2,21 +2,24 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Collections.Immutable;
using System.IO;
+using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Razor.Compiler.CSharp;
namespace Microsoft.NET.Sdk.Razor.SourceGenerators
{
public partial class RazorSourceGenerator
{
- private (RazorSourceGenerationOptions?, Diagnostic?) ComputeRazorSourceGeneratorOptions(((AnalyzerConfigOptionsProvider, ParseOptions), bool) pair, CancellationToken ct)
+ private (RazorSourceGenerationOptions?, Diagnostic?) ComputeRazorSourceGeneratorOptions((((AnalyzerConfigOptionsProvider, ParseOptions), ImmutableArray), bool) pair, CancellationToken ct)
{
- var ((options, parseOptions), isSuppressed) = pair;
+ var (((options, parseOptions), references), isSuppressed) = pair;
var globalOptions = options.GlobalOptions;
if (isSuppressed)
@@ -42,7 +45,15 @@ public partial class RazorSourceGenerator
razorLanguageVersion = RazorLanguageVersion.Latest;
}
- var razorConfiguration = new RazorConfiguration(razorLanguageVersion, configurationName ?? "default", Extensions: [], UseConsolidatedMvcViews: true);
+ var minimalReferences = references
+ .Where(r => r.Display is { } display && display.EndsWith("Microsoft.AspNetCore.Components.dll", StringComparison.Ordinal))
+ .ToImmutableArray();
+
+ var isComponentParameterSupported = minimalReferences.Length == 0
+ ? false
+ : CSharpCompilation.Create("components", references: minimalReferences).HasAddComponentParameter();
+
+ var razorConfiguration = new RazorConfiguration(razorLanguageVersion, configurationName ?? "default", Extensions: [], UseConsolidatedMvcViews: true, SuppressAddComponentParameter: !isComponentParameterSupported);
// We use the new tokenizer by default
var useRazorTokenizer = !parseOptions.Features.TryGetValue("use-razor-tokenizer", out var useRazorTokenizerValue)
@@ -86,7 +97,7 @@ private static (SourceGeneratorProjectItem?, Diagnostic?) ComputeProjectItems((A
.Replace(Path.DirectorySeparatorChar, '/')
.Replace("//", "/"),
relativePhysicalPath: relativePath,
- fileKind: additionalText.Path.EndsWith(".razor", StringComparison.OrdinalIgnoreCase) ? FileKinds.Component : FileKinds.Legacy,
+ fileKind: FileKinds.GetFileKindFromFilePath(additionalText.Path),
additionalText: additionalText,
cssScope: cssScope);
return (projectItem, null);
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs
index 0fe65e3eb60..9d3eff80c26 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorSourceGenerator.cs
@@ -6,7 +6,6 @@
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.AspNetCore.Razor.Language.Extensions;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
@@ -44,6 +43,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
var razorSourceGeneratorOptions = analyzerConfigOptions
.Combine(parseOptions)
+ .Combine(metadataRefs.Collect())
.SuppressIfNeeded(isGeneratorSuppressed)
.Select(ComputeRazorSourceGeneratorOptions)
.ReportDiagnostics(context);
@@ -235,30 +235,16 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
var razorHostOutputsEnabled = analyzerConfigOptions.CheckGlobalFlagSet("EnableRazorHostOutputs");
var withOptionsDesignTime = withOptions.EmptyOrCachedWhen(razorHostOutputsEnabled, false);
- var isAddComponentParameterAvailable = metadataRefs
- .Where(r => r.Display is { } display && display.EndsWith("Microsoft.AspNetCore.Components.dll", StringComparison.Ordinal))
- .Collect()
- .Select((refs, _) =>
- {
- var compilation = CSharpCompilation.Create("components", references: refs);
- return compilation.GetTypesByMetadataName("Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder")
- .Any(static t =>
- t.DeclaredAccessibility == Accessibility.Public &&
- t.GetMembers("AddComponentParameter")
- .Any(static m => m.DeclaredAccessibility == Accessibility.Public));
- });
-
IncrementalValuesProvider<(string, SourceGeneratorRazorCodeDocument)> processed(bool designTime)
{
return (designTime ? withOptionsDesignTime : withOptions)
- .Combine(isAddComponentParameterAvailable)
.Select((pair, _) =>
{
- var (((sourceItem, imports), razorSourceGeneratorOptions), isAddComponentParameterAvailable) = pair;
+ var ((sourceItem, imports), razorSourceGeneratorOptions) = pair;
RazorSourceGeneratorEventSource.Log.ParseRazorDocumentStart(sourceItem.RelativePhysicalPath);
- var projectEngine = GetGenerationProjectEngine(sourceItem, imports, razorSourceGeneratorOptions, isAddComponentParameterAvailable);
+ var projectEngine = GetGenerationProjectEngine(sourceItem, imports, razorSourceGeneratorOptions);
var document = projectEngine.ProcessInitialParse(sourceItem, designTime);
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/BaseTagHelperDescriptorProviderTest.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/BaseTagHelperDescriptorProviderTest.cs
index afc107b1499..13404d95a58 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/BaseTagHelperDescriptorProviderTest.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/BaseTagHelperDescriptorProviderTest.cs
@@ -7,24 +7,39 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language;
+using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Razor;
public abstract class TagHelperDescriptorProviderTestBase
{
- static TagHelperDescriptorProviderTestBase()
+ protected TagHelperDescriptorProviderTestBase(string additionalCodeOpt = null)
{
- BaseCompilation = TestCompilation.Create(typeof(ComponentTagHelperDescriptorProviderTest).Assembly);
CSharpParseOptions = new CSharpParseOptions(LanguageVersion.CSharp7_3);
+ var testTagHelpers = CSharpCompilation.Create(
+ assemblyName: AssemblyName,
+ syntaxTrees:
+ [
+ Parse(TagHelperDescriptorFactoryTagHelpers.Code),
+ ..(additionalCodeOpt != null ? [Parse(additionalCodeOpt)] : Enumerable.Empty()),
+ ],
+ references: ReferenceUtil.AspNetLatestAll,
+ options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
+ BaseCompilation = TestCompilation.Create(
+ syntaxTrees: [],
+ references: [testTagHelpers.VerifyDiagnostics().EmitToImageReference()]);
}
- protected static Compilation BaseCompilation { get; }
+ protected Compilation BaseCompilation { get; }
- protected static CSharpParseOptions CSharpParseOptions { get; }
+ protected CSharpParseOptions CSharpParseOptions { get; }
- protected static CSharpSyntaxTree Parse(string text)
+ protected static string AssemblyName { get; } = "Microsoft.CodeAnalysis.Razor.Test";
+
+ protected CSharpSyntaxTree Parse(string text)
{
return (CSharpSyntaxTree)CSharpSyntaxTree.ParseText(text, CSharpParseOptions);
}
@@ -35,9 +50,7 @@ protected static TagHelperDescriptor[] ExcludeBuiltInComponents(TagHelperDescrip
{
var results =
context.Results
- .Where(c => c.AssemblyName != "Microsoft.AspNetCore.Razor.Test.ComponentShim")
- .Where(c => !c.DisplayName.StartsWith("Microsoft.AspNetCore.Components.Web", StringComparison.Ordinal))
- .Where(c => c.GetTypeName() != "Microsoft.AspNetCore.Components.Bind")
+ .Where(c => !c.DisplayName.StartsWith("Microsoft.AspNetCore.Components.", StringComparison.Ordinal))
.OrderBy(c => c.Name)
.ToArray();
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/CompilationTagHelperFeatureTest.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/CompilationTagHelperFeatureTest.cs
index ce7156f1c60..2b93c3a4bf2 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/CompilationTagHelperFeatureTest.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/CompilationTagHelperFeatureTest.cs
@@ -5,7 +5,7 @@
using System.Linq;
using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.AspNetCore.Razor.TagHelpers;
+using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.NET.Sdk.Razor.SourceGenerators;
using Moq;
@@ -21,8 +21,8 @@ public void IsValidCompilation_ReturnsTrueIfTagHelperInterfaceCannotBeFound()
// Arrange
var references = new[]
{
- MetadataReference.CreateFromFile(typeof(string).Assembly.Location),
- };
+ ReferenceUtil.NetLatestSystemRuntime,
+ };
var compilation = CSharpCompilation.Create("Test", references: references);
// Act
@@ -38,8 +38,8 @@ public void IsValidCompilation_ReturnsFalseIfSystemStringCannotBeFound()
// Arrange
var references = new[]
{
- MetadataReference.CreateFromFile(typeof(ITagHelper).Assembly.Location),
- };
+ ReferenceUtil.AspNetLatestRazor,
+ };
var compilation = CSharpCompilation.Create("Test", references: references);
// Act
@@ -55,9 +55,9 @@ public void IsValidCompilation_ReturnsTrueIfWellKnownTypesAreFound()
// Arrange
var references = new[]
{
- MetadataReference.CreateFromFile(typeof(string).Assembly.Location),
- MetadataReference.CreateFromFile(typeof(ITagHelper).Assembly.Location),
- };
+ ReferenceUtil.NetLatestSystemRuntime,
+ ReferenceUtil.AspNetLatestRazor,
+ };
var compilation = CSharpCompilation.Create("Test", references: references);
// Act
@@ -106,9 +106,9 @@ public void GetDescriptors_SetsCompilation_IfCompilationIsValid()
var references = new[]
{
- MetadataReference.CreateFromFile(typeof(string).Assembly.Location),
- MetadataReference.CreateFromFile(typeof(ITagHelper).Assembly.Location),
- };
+ ReferenceUtil.NetLatestSystemRuntime,
+ ReferenceUtil.AspNetLatestRazor,
+ };
var engine = RazorProjectEngine.Create(
configure =>
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/ComponentTagHelperDescriptorProviderTest.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/ComponentTagHelperDescriptorProviderTest.cs
index 3a37a47cd1b..b1549968c4d 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/ComponentTagHelperDescriptorProviderTest.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/ComponentTagHelperDescriptorProviderTest.cs
@@ -1620,7 +1620,7 @@ public Task SetParametersAsync(ParameterView parameters)
Assert.Empty(compilation.GetDiagnostics());
var targetSymbol = (IAssemblySymbol)compilation.GetAssemblyOrModuleSymbol(
- compilation.References.First(static r => r.Display.Contains("Microsoft.CodeAnalysis.Razor.Test.dll")));
+ compilation.References.First(static r => r.Display.Contains("Microsoft.CodeAnalysis.Razor.Test")));
var context = new TagHelperDescriptorProviderContext(compilation, targetSymbol);
var provider = new ComponentTagHelperDescriptorProvider();
diff --git a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/DefaultTagHelperDescriptorFactoryTest.cs b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/DefaultTagHelperDescriptorFactoryTest.cs
index d76829adccb..f1a6bea4038 100644
--- a/src/Compiler/Microsoft.CodeAnalysis.Razor/test/DefaultTagHelperDescriptorFactoryTest.cs
+++ b/src/Compiler/Microsoft.CodeAnalysis.Razor/test/DefaultTagHelperDescriptorFactoryTest.cs
@@ -7,26 +7,21 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using System.Reflection;
using Microsoft.AspNetCore.Razor.Language;
-using Microsoft.AspNetCore.Razor.Language.Legacy;
using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.Razor.Workspaces.Test;
using Xunit;
using static Microsoft.AspNetCore.Razor.Language.CommonMetadata;
namespace Microsoft.CodeAnalysis.Razor.Workspaces;
-public class DefaultTagHelperDescriptorFactoryTest
+public class DefaultTagHelperDescriptorFactoryTest : TagHelperDescriptorProviderTestBase
{
- private static readonly Assembly _assembly = typeof(DefaultTagHelperDescriptorFactoryTest).GetTypeInfo().Assembly;
-
- protected static readonly AssemblyName TagHelperDescriptorFactoryTestAssembly = _assembly.GetName();
-
- protected static readonly string AssemblyName = TagHelperDescriptorFactoryTestAssembly.Name;
+ public DefaultTagHelperDescriptorFactoryTest() : base(AdditionalCode)
+ {
+ Compilation = BaseCompilation;
+ }
- private static Compilation Compilation { get; } = TestCompilation.Create(_assembly);
+ private Compilation Compilation { get; }
public static TheoryData RequiredAttributeParserErrorData
{
@@ -324,66 +319,66 @@ public static TheoryData IsEnumData
get
{
// tagHelperType, expectedDescriptor
- return new TheoryData
+ return new TheoryData
{
{
- typeof(EnumTagHelper),
- TagHelperDescriptorBuilder.Create(typeof(EnumTagHelper).FullName, AssemblyName)
- .Metadata(GetMetadata())
+ "TestNamespace.EnumTagHelper",
+ TagHelperDescriptorBuilder.Create("TestNamespace.EnumTagHelper", AssemblyName)
+ .Metadata(GetMetadata("TestNamespace", "EnumTagHelper"))
.TagMatchingRuleDescriptor(ruleBuilder => ruleBuilder.RequireTagName("enum"))
.BoundAttributeDescriptor(builder =>
builder
.Name("non-enum-property")
- .Metadata(PropertyName(nameof(EnumTagHelper.NonEnumProperty)))
+ .Metadata(PropertyName("NonEnumProperty"))
.TypeName(typeof(int).FullName))
.BoundAttributeDescriptor(builder =>
builder
.Name("enum-property")
- .Metadata(PropertyName(nameof(EnumTagHelper.EnumProperty)))
- .TypeName(typeof(CustomEnum).FullName)
+ .Metadata(PropertyName("EnumProperty"))
+ .TypeName("TestNamespace.CustomEnum")
.AsEnum())
.Build()
},
{
- typeof(MultiEnumTagHelper),
- TagHelperDescriptorBuilder.Create(typeof(MultiEnumTagHelper).FullName, AssemblyName)
- .Metadata(GetMetadata())
+ "TestNamespace.MultiEnumTagHelper",
+ TagHelperDescriptorBuilder.Create("TestNamespace.MultiEnumTagHelper", AssemblyName)
+ .Metadata(GetMetadata("TestNamespace", "MultiEnumTagHelper"))
.TagMatchingRuleDescriptor(ruleBuilder => ruleBuilder.RequireTagName("p"))
.TagMatchingRuleDescriptor(ruleBuilder => ruleBuilder.RequireTagName("input"))
.BoundAttributeDescriptor(builder =>
builder
.Name("non-enum-property")
- .Metadata(PropertyName(nameof(MultiEnumTagHelper.NonEnumProperty)))
+ .Metadata(PropertyName("NonEnumProperty"))
.TypeName(typeof(int).FullName))
.BoundAttributeDescriptor(builder =>
builder
.Name("enum-property")
- .Metadata(PropertyName(nameof(MultiEnumTagHelper.EnumProperty)))
- .TypeName(typeof(CustomEnum).FullName)
+ .Metadata(PropertyName("EnumProperty"))
+ .TypeName("TestNamespace.CustomEnum")
.AsEnum())
.Build()
},
{
- typeof(NestedEnumTagHelper),
- TagHelperDescriptorBuilder.Create(typeof(NestedEnumTagHelper).FullName, AssemblyName)
- .Metadata(GetMetadata())
+ "TestNamespace.NestedEnumTagHelper",
+ TagHelperDescriptorBuilder.Create("TestNamespace.NestedEnumTagHelper", AssemblyName)
+ .Metadata(GetMetadata("TestNamespace", "NestedEnumTagHelper"))
.TagMatchingRuleDescriptor(ruleBuilder => ruleBuilder.RequireTagName("nested-enum"))
.BoundAttributeDescriptor(builder =>
builder
.Name("nested-enum-property")
- .Metadata(PropertyName(nameof(NestedEnumTagHelper.NestedEnumProperty)))
- .TypeName($"{typeof(NestedEnumTagHelper).FullName}.{nameof(NestedEnumTagHelper.NestedEnum)}")
+ .Metadata(PropertyName("NestedEnumProperty"))
+ .TypeName("TestNamespace.NestedEnumTagHelper.NestedEnum")
.AsEnum())
.BoundAttributeDescriptor(builder =>
builder
.Name("non-enum-property")
- .Metadata(PropertyName(nameof(NestedEnumTagHelper.NonEnumProperty)))
+ .Metadata(PropertyName("NonEnumProperty"))
.TypeName(typeof(int).FullName))
.BoundAttributeDescriptor(builder =>
builder
.Name("enum-property")
- .Metadata(PropertyName(nameof(NestedEnumTagHelper.EnumProperty)))
- .TypeName(typeof(CustomEnum).FullName)
+ .Metadata(PropertyName("EnumProperty"))
+ .TypeName("TestNamespace.CustomEnum")
.AsEnum())
.Build()
},
@@ -394,12 +389,12 @@ public static TheoryData IsEnumData
[Theory]
[MemberData(nameof(IsEnumData))]
public void CreateDescriptor_IsEnumIsSetCorrectly(
- Type tagHelperType,
+ string tagHelperTypeFullName,
TagHelperDescriptor expectedDescriptor)
{
// Arrange
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperType.FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperTypeFullName);
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -413,27 +408,27 @@ public static TheoryData RequiredParentData
get
{
// tagHelperType, expectedDescriptor
- return new TheoryData
+ return new TheoryData
{
{
- typeof(RequiredParentTagHelper),
- TagHelperDescriptorBuilder.Create(typeof(RequiredParentTagHelper).FullName, AssemblyName)
- .Metadata(GetMetadata())
+ "TestNamespace.RequiredParentTagHelper",
+ TagHelperDescriptorBuilder.Create("TestNamespace.RequiredParentTagHelper", AssemblyName)
+ .Metadata(GetMetadata("TestNamespace", "RequiredParentTagHelper"))
.TagMatchingRuleDescriptor(builder => builder.RequireTagName("input").RequireParentTag("div"))
.Build()
},
{
- typeof(MultiSpecifiedRequiredParentTagHelper),
- TagHelperDescriptorBuilder.Create(typeof(MultiSpecifiedRequiredParentTagHelper).FullName, AssemblyName)
- .Metadata(GetMetadata())
+ "TestNamespace.MultiSpecifiedRequiredParentTagHelper",
+ TagHelperDescriptorBuilder.Create("TestNamespace.MultiSpecifiedRequiredParentTagHelper", AssemblyName)
+ .Metadata(GetMetadata("TestNamespace", "MultiSpecifiedRequiredParentTagHelper"))
.TagMatchingRuleDescriptor(builder => builder.RequireTagName("p").RequireParentTag("div"))
.TagMatchingRuleDescriptor(builder => builder.RequireTagName("input").RequireParentTag("section"))
.Build()
},
{
- typeof(MultiWithUnspecifiedRequiredParentTagHelper),
- TagHelperDescriptorBuilder.Create(typeof(MultiWithUnspecifiedRequiredParentTagHelper).FullName, AssemblyName)
- .Metadata(GetMetadata())
+ "TestNamespace.MultiWithUnspecifiedRequiredParentTagHelper",
+ TagHelperDescriptorBuilder.Create("TestNamespace.MultiWithUnspecifiedRequiredParentTagHelper", AssemblyName)
+ .Metadata(GetMetadata("TestNamespace", "MultiWithUnspecifiedRequiredParentTagHelper"))
.TagMatchingRuleDescriptor(builder => builder.RequireTagName("p"))
.TagMatchingRuleDescriptor(builder => builder.RequireTagName("input").RequireParentTag("div"))
.Build()
@@ -445,12 +440,12 @@ public static TheoryData RequiredParentData
[Theory]
[MemberData(nameof(RequiredParentData))]
public void CreateDescriptor_CreatesDesignTimeDescriptorsWithRequiredParent(
- Type tagHelperType,
+ string tagHelperTypeFullName,
TagHelperDescriptor expectedDescriptor)
{
// Arrange
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperType.FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperTypeFullName);
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -459,16 +454,14 @@ public void CreateDescriptor_CreatesDesignTimeDescriptorsWithRequiredParent(
Assert.Equal(expectedDescriptor, descriptor);
}
- private static KeyValuePair[] GetMetadata()
+ private static KeyValuePair[] GetMetadata(string @namespace, string name)
{
- var type = typeof(T);
- var name = type.Name;
- var fullName = type.FullName;
+ var fullName = $"{@namespace}.{name}";
return new[]
{
TypeName(fullName),
- TypeNamespace(fullName[..(fullName.Length - name.Length - 1)]),
+ TypeNamespace(@namespace),
TypeNameIdentifier(name)
};
}
@@ -478,29 +471,29 @@ public static TheoryData RestrictChildrenData
get
{
// tagHelperType, expectedDescriptor
- return new TheoryData
+ return new TheoryData
{
{
- typeof(RestrictChildrenTagHelper),
- TagHelperDescriptorBuilder.Create(typeof(RestrictChildrenTagHelper).FullName, AssemblyName)
- .Metadata(GetMetadata())
+ "TestNamespace.RestrictChildrenTagHelper",
+ TagHelperDescriptorBuilder.Create("TestNamespace.RestrictChildrenTagHelper", AssemblyName)
+ .Metadata(GetMetadata("TestNamespace", "RestrictChildrenTagHelper"))
.TagMatchingRuleDescriptor(builder => builder.RequireTagName("restrict-children"))
.AllowChildTag("p")
.Build()
},
{
- typeof(DoubleRestrictChildrenTagHelper),
- TagHelperDescriptorBuilder.Create(typeof(DoubleRestrictChildrenTagHelper).FullName, AssemblyName)
- .Metadata(GetMetadata())
+ "TestNamespace.DoubleRestrictChildrenTagHelper",
+ TagHelperDescriptorBuilder.Create("TestNamespace.DoubleRestrictChildrenTagHelper", AssemblyName)
+ .Metadata(GetMetadata("TestNamespace", "DoubleRestrictChildrenTagHelper"))
.TagMatchingRuleDescriptor(builder => builder.RequireTagName("double-restrict-children"))
.AllowChildTag("p")
.AllowChildTag("strong")
.Build()
},
{
- typeof(MultiTargetRestrictChildrenTagHelper),
- TagHelperDescriptorBuilder.Create(typeof(MultiTargetRestrictChildrenTagHelper).FullName, AssemblyName)
- .Metadata(GetMetadata())
+ "TestNamespace.MultiTargetRestrictChildrenTagHelper",
+ TagHelperDescriptorBuilder.Create("TestNamespace.MultiTargetRestrictChildrenTagHelper", AssemblyName)
+ .Metadata(GetMetadata("TestNamespace", "MultiTargetRestrictChildrenTagHelper"))
.TagMatchingRuleDescriptor(builder => builder.RequireTagName("p"))
.TagMatchingRuleDescriptor(builder => builder.RequireTagName("div"))
.AllowChildTag("p")
@@ -515,12 +508,12 @@ public static TheoryData RestrictChildrenData
[Theory]
[MemberData(nameof(RestrictChildrenData))]
public void CreateDescriptor_CreatesDescriptorsWithAllowedChildren(
- Type tagHelperType,
+ string tagHelperTypeFullName,
TagHelperDescriptor expectedDescriptor)
{
// Arrange
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperType.FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperTypeFullName);
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -534,21 +527,21 @@ public static TheoryData TagStructureData
get
{
// tagHelperType, expectedDescriptor
- return new TheoryData
+ return new TheoryData
{
{
- typeof(TagStructureTagHelper),
- TagHelperDescriptorBuilder.Create(typeof(TagStructureTagHelper).FullName, AssemblyName)
- .Metadata(GetMetadata())
+ "TestNamespace.TagStructureTagHelper",
+ TagHelperDescriptorBuilder.Create("TestNamespace.TagStructureTagHelper", AssemblyName)
+ .Metadata(GetMetadata("TestNamespace", "TagStructureTagHelper"))
.TagMatchingRuleDescriptor(builder => builder
.RequireTagName("input")
.RequireTagStructure(TagStructure.WithoutEndTag))
.Build()
},
{
- typeof(MultiSpecifiedTagStructureTagHelper),
- TagHelperDescriptorBuilder.Create(typeof(MultiSpecifiedTagStructureTagHelper).FullName, AssemblyName)
- .Metadata(GetMetadata())
+ "TestNamespace.MultiSpecifiedTagStructureTagHelper",
+ TagHelperDescriptorBuilder.Create("TestNamespace.MultiSpecifiedTagStructureTagHelper", AssemblyName)
+ .Metadata(GetMetadata("TestNamespace", "MultiSpecifiedTagStructureTagHelper"))
.TagMatchingRuleDescriptor(builder => builder
.RequireTagName("p")
.RequireTagStructure(TagStructure.NormalOrSelfClosing))
@@ -558,9 +551,9 @@ public static TheoryData TagStructureData
.Build()
},
{
- typeof(MultiWithUnspecifiedTagStructureTagHelper),
- TagHelperDescriptorBuilder.Create(typeof(MultiWithUnspecifiedTagStructureTagHelper).FullName, AssemblyName)
- .Metadata(GetMetadata())
+ "TestNamespace.MultiWithUnspecifiedTagStructureTagHelper",
+ TagHelperDescriptorBuilder.Create("TestNamespace.MultiWithUnspecifiedTagStructureTagHelper", AssemblyName)
+ .Metadata(GetMetadata("TestNamespace", "MultiWithUnspecifiedTagStructureTagHelper"))
.TagMatchingRuleDescriptor(builder => builder
.RequireTagName("p"))
.TagMatchingRuleDescriptor(builder => builder
@@ -575,12 +568,12 @@ public static TheoryData TagStructureData
[Theory]
[MemberData(nameof(TagStructureData))]
public void CreateDescriptor_CreatesDesignTimeDescriptorsWithTagStructure(
- Type tagHelperType,
+ string tagHelperTypeFullName,
TagHelperDescriptor expectedDescriptor)
{
// Arrange
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperType.FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperTypeFullName);
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -594,174 +587,174 @@ public static TheoryData EditorBrowsableData
get
{
// tagHelperType, designTime, expectedDescriptor
- return new TheoryData
+ return new TheoryData
{
{
- typeof(InheritedEditorBrowsableTagHelper),
+ "TestNamespace.InheritedEditorBrowsableTagHelper",
true,
CreateTagHelperDescriptor(
tagName: "inherited-editor-browsable",
- typeName: typeof(InheritedEditorBrowsableTagHelper).FullName,
+ typeName: "TestNamespace.InheritedEditorBrowsableTagHelper",
assemblyName: AssemblyName,
- typeNamespace: typeof(InheritedEditorBrowsableTagHelper).FullName.Substring(0, typeof(InheritedEditorBrowsableTagHelper).FullName.Length - nameof(InheritedEditorBrowsableTagHelper).Length -1),
- typeNameIdentifier: nameof(InheritedEditorBrowsableTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "InheritedEditorBrowsableTagHelper",
attributes: new Action[]
{
builder => builder
.Name("property")
- .Metadata(PropertyName(nameof(InheritedEditorBrowsableTagHelper.Property)))
+ .Metadata(PropertyName("Property"))
.TypeName(typeof(int).FullName),
})
},
- { typeof(EditorBrowsableTagHelper), true, null },
+ { "TestNamespace.EditorBrowsableTagHelper", true, null },
{
- typeof(EditorBrowsableTagHelper),
+ "TestNamespace.EditorBrowsableTagHelper",
false,
CreateTagHelperDescriptor(
tagName: "editor-browsable",
- typeName: typeof(EditorBrowsableTagHelper).FullName,
+ typeName: "TestNamespace.EditorBrowsableTagHelper",
assemblyName: AssemblyName,
- typeNamespace: typeof(EditorBrowsableTagHelper).FullName.Substring(0, typeof(EditorBrowsableTagHelper).FullName.Length - nameof(EditorBrowsableTagHelper).Length -1),
- typeNameIdentifier: nameof(EditorBrowsableTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "EditorBrowsableTagHelper",
attributes: new Action[]
{
builder => builder
.Name("property")
- .Metadata(PropertyName(nameof(EditorBrowsableTagHelper.Property)))
+ .Metadata(PropertyName("Property"))
.TypeName(typeof(int).FullName),
})
},
{
- typeof(HiddenPropertyEditorBrowsableTagHelper),
+ "TestNamespace.HiddenPropertyEditorBrowsableTagHelper",
true,
CreateTagHelperDescriptor(
tagName: "hidden-property-editor-browsable",
- typeName: typeof(HiddenPropertyEditorBrowsableTagHelper).FullName,
- typeNamespace: typeof(HiddenPropertyEditorBrowsableTagHelper).FullName.Substring(0, typeof(HiddenPropertyEditorBrowsableTagHelper).FullName.Length - nameof(HiddenPropertyEditorBrowsableTagHelper).Length -1),
- typeNameIdentifier: nameof(HiddenPropertyEditorBrowsableTagHelper),
+ typeName: "TestNamespace.HiddenPropertyEditorBrowsableTagHelper",
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "HiddenPropertyEditorBrowsableTagHelper",
assemblyName: AssemblyName)
},
{
- typeof(HiddenPropertyEditorBrowsableTagHelper),
+ "TestNamespace.HiddenPropertyEditorBrowsableTagHelper",
false,
CreateTagHelperDescriptor(
tagName: "hidden-property-editor-browsable",
- typeName: typeof(HiddenPropertyEditorBrowsableTagHelper).FullName,
- typeNamespace: typeof(HiddenPropertyEditorBrowsableTagHelper).FullName.Substring(0, typeof(HiddenPropertyEditorBrowsableTagHelper).FullName.Length - nameof(HiddenPropertyEditorBrowsableTagHelper).Length -1),
- typeNameIdentifier: nameof(HiddenPropertyEditorBrowsableTagHelper),
+ typeName: "TestNamespace.HiddenPropertyEditorBrowsableTagHelper",
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "HiddenPropertyEditorBrowsableTagHelper",
assemblyName: AssemblyName,
attributes: new Action[]
{
builder => builder
.Name("property")
- .Metadata(PropertyName(nameof(HiddenPropertyEditorBrowsableTagHelper.Property)))
+ .Metadata(PropertyName("Property"))
.TypeName(typeof(int).FullName),
})
},
{
- typeof(OverriddenEditorBrowsableTagHelper),
+ "TestNamespace.OverriddenEditorBrowsableTagHelper",
true,
CreateTagHelperDescriptor(
tagName: "overridden-editor-browsable",
- typeName: typeof(OverriddenEditorBrowsableTagHelper).FullName,
- typeNamespace: typeof(OverriddenEditorBrowsableTagHelper).FullName.Substring(0, typeof(OverriddenEditorBrowsableTagHelper).FullName.Length - nameof(OverriddenEditorBrowsableTagHelper).Length -1),
- typeNameIdentifier: nameof(OverriddenEditorBrowsableTagHelper),
+ typeName: "TestNamespace.OverriddenEditorBrowsableTagHelper",
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "OverriddenEditorBrowsableTagHelper",
assemblyName: AssemblyName,
attributes: new Action[]
{
builder => builder
.Name("property")
- .Metadata(PropertyName(nameof(OverriddenEditorBrowsableTagHelper.Property)))
+ .Metadata(PropertyName("Property"))
.TypeName(typeof(int).FullName),
})
},
{
- typeof(MultiPropertyEditorBrowsableTagHelper),
+ "TestNamespace.MultiPropertyEditorBrowsableTagHelper",
true,
CreateTagHelperDescriptor(
tagName: "multi-property-editor-browsable",
- typeName: typeof(MultiPropertyEditorBrowsableTagHelper).FullName,
- typeNamespace: typeof(MultiPropertyEditorBrowsableTagHelper).FullName.Substring(0, typeof(MultiPropertyEditorBrowsableTagHelper).FullName.Length - nameof(MultiPropertyEditorBrowsableTagHelper).Length -1),
- typeNameIdentifier: nameof(MultiPropertyEditorBrowsableTagHelper),
+ typeName: "TestNamespace.MultiPropertyEditorBrowsableTagHelper",
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "MultiPropertyEditorBrowsableTagHelper",
assemblyName: AssemblyName,
attributes: new Action[]
{
builder => builder
.Name("property2")
- .Metadata(PropertyName(nameof(MultiPropertyEditorBrowsableTagHelper.Property2)))
+ .Metadata(PropertyName("Property2"))
.TypeName(typeof(int).FullName),
})
},
{
- typeof(MultiPropertyEditorBrowsableTagHelper),
+ "TestNamespace.MultiPropertyEditorBrowsableTagHelper",
false,
CreateTagHelperDescriptor(
tagName: "multi-property-editor-browsable",
- typeName: typeof(MultiPropertyEditorBrowsableTagHelper).FullName,
- typeNamespace: typeof(MultiPropertyEditorBrowsableTagHelper).FullName.Substring(0, typeof(MultiPropertyEditorBrowsableTagHelper).FullName.Length - nameof(MultiPropertyEditorBrowsableTagHelper).Length -1),
- typeNameIdentifier: nameof(MultiPropertyEditorBrowsableTagHelper),
+ typeName: "TestNamespace.MultiPropertyEditorBrowsableTagHelper",
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "MultiPropertyEditorBrowsableTagHelper",
assemblyName: AssemblyName,
attributes: new Action[]
{
builder => builder
.Name("property")
- .Metadata(PropertyName(nameof(MultiPropertyEditorBrowsableTagHelper.Property)))
+ .Metadata(PropertyName("Property"))
.TypeName(typeof(int).FullName),
builder => builder
.Name("property2")
- .Metadata(PropertyName(nameof(MultiPropertyEditorBrowsableTagHelper.Property2)))
+ .Metadata(PropertyName("Property2"))
.TypeName(typeof(int).FullName),
})
},
{
- typeof(OverriddenPropertyEditorBrowsableTagHelper),
+ "TestNamespace.OverriddenPropertyEditorBrowsableTagHelper",
true,
CreateTagHelperDescriptor(
tagName: "overridden-property-editor-browsable",
- typeName: typeof(OverriddenPropertyEditorBrowsableTagHelper).FullName,
- typeNamespace: typeof(OverriddenPropertyEditorBrowsableTagHelper).FullName.Substring(0, typeof(OverriddenPropertyEditorBrowsableTagHelper).FullName.Length - nameof(OverriddenPropertyEditorBrowsableTagHelper).Length -1),
- typeNameIdentifier: nameof(OverriddenPropertyEditorBrowsableTagHelper),
+ typeName: "TestNamespace.OverriddenPropertyEditorBrowsableTagHelper",
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "OverriddenPropertyEditorBrowsableTagHelper",
assemblyName: AssemblyName)
},
{
- typeof(OverriddenPropertyEditorBrowsableTagHelper),
+ "TestNamespace.OverriddenPropertyEditorBrowsableTagHelper",
false,
CreateTagHelperDescriptor(
tagName: "overridden-property-editor-browsable",
- typeName: typeof(OverriddenPropertyEditorBrowsableTagHelper).FullName,
- typeNamespace: typeof(OverriddenPropertyEditorBrowsableTagHelper).FullName.Substring(0, typeof(OverriddenPropertyEditorBrowsableTagHelper).FullName.Length - nameof(OverriddenPropertyEditorBrowsableTagHelper).Length -1),
- typeNameIdentifier: nameof(OverriddenPropertyEditorBrowsableTagHelper),
+ typeName: "TestNamespace.OverriddenPropertyEditorBrowsableTagHelper",
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "OverriddenPropertyEditorBrowsableTagHelper",
assemblyName: AssemblyName,
attributes: new Action[]
{
builder => builder
.Name("property2")
- .Metadata(PropertyName(nameof(OverriddenPropertyEditorBrowsableTagHelper.Property2)))
+ .Metadata(PropertyName("Property2"))
.TypeName(typeof(int).FullName),
builder => builder
.Name("property")
- .Metadata(PropertyName(nameof(OverriddenPropertyEditorBrowsableTagHelper.Property)))
+ .Metadata(PropertyName("Property"))
.TypeName(typeof(int).FullName),
})
},
{
- typeof(DefaultEditorBrowsableTagHelper),
+ "TestNamespace.DefaultEditorBrowsableTagHelper",
true,
CreateTagHelperDescriptor(
tagName: "default-editor-browsable",
- typeName: typeof(DefaultEditorBrowsableTagHelper).FullName,
- typeNamespace: typeof(DefaultEditorBrowsableTagHelper).FullName.Substring(0, typeof(DefaultEditorBrowsableTagHelper).FullName.Length - nameof(DefaultEditorBrowsableTagHelper).Length -1),
- typeNameIdentifier: nameof(DefaultEditorBrowsableTagHelper),
+ typeName: "TestNamespace.DefaultEditorBrowsableTagHelper",
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "DefaultEditorBrowsableTagHelper",
assemblyName: AssemblyName,
attributes: new Action[]
{
builder => builder
.Name("property")
- .Metadata(PropertyName(nameof(DefaultEditorBrowsableTagHelper.Property)))
+ .Metadata(PropertyName("Property"))
.TypeName(typeof(int).FullName),
})
},
- { typeof(MultiEditorBrowsableTagHelper), true, null }
+ { "TestNamespace.MultiEditorBrowsableTagHelper", true, null }
};
}
}
@@ -769,13 +762,13 @@ public static TheoryData EditorBrowsableData
[Theory]
[MemberData(nameof(EditorBrowsableData))]
public void CreateDescriptor_UnderstandsEditorBrowsableAttribute(
- Type tagHelperType,
+ string tagHelperTypeFullName,
bool designTime,
TagHelperDescriptor expectedDescriptor)
{
// Arrange
var factory = new DefaultTagHelperDescriptorFactory(Compilation, designTime, designTime);
- var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperType.FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperTypeFullName);
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -791,29 +784,29 @@ public static TheoryData AttributeTargetData
var attributes = Enumerable.Empty();
// tagHelperType, expectedDescriptor
- return new TheoryData
+ return new TheoryData
{
{
- typeof(AttributeTargetingTagHelper),
+ "TestNamespace.AttributeTargetingTagHelper",
CreateTagHelperDescriptor(
TagHelperMatchingConventions.ElementCatchAllName,
- typeof(AttributeTargetingTagHelper).FullName,
+ "TestNamespace.AttributeTargetingTagHelper",
AssemblyName,
- typeof(AttributeTargetingTagHelper).FullName.Substring(0, typeof(AttributeTargetingTagHelper).FullName.Length - nameof(AttributeTargetingTagHelper).Length -1),
- nameof(AttributeTargetingTagHelper),
+ "TestNamespace",
+ "AttributeTargetingTagHelper",
ruleBuilders: new Action[]
{
builder => builder.RequireAttributeDescriptor(attribute => attribute.Name("class")),
})
},
{
- typeof(MultiAttributeTargetingTagHelper),
+ "TestNamespace.MultiAttributeTargetingTagHelper",
CreateTagHelperDescriptor(
TagHelperMatchingConventions.ElementCatchAllName,
- typeof(MultiAttributeTargetingTagHelper).FullName,
+ "TestNamespace.MultiAttributeTargetingTagHelper",
AssemblyName,
- typeNamespace: typeof(MultiAttributeTargetingTagHelper).FullName.Substring(0, typeof(MultiAttributeTargetingTagHelper).FullName.Length - nameof(MultiAttributeTargetingTagHelper).Length -1),
- typeNameIdentifier: nameof(MultiAttributeTargetingTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "MultiAttributeTargetingTagHelper",
ruleBuilders: new Action[]
{
builder =>
@@ -825,13 +818,13 @@ public static TheoryData AttributeTargetData
})
},
{
- typeof(MultiAttributeAttributeTargetingTagHelper),
+ "TestNamespace.MultiAttributeAttributeTargetingTagHelper",
CreateTagHelperDescriptor(
TagHelperMatchingConventions.ElementCatchAllName,
- typeof(MultiAttributeAttributeTargetingTagHelper).FullName,
+ "TestNamespace.MultiAttributeAttributeTargetingTagHelper",
AssemblyName,
- typeNamespace: typeof(MultiAttributeAttributeTargetingTagHelper).FullName.Substring(0, typeof(MultiAttributeAttributeTargetingTagHelper).FullName.Length - nameof(MultiAttributeAttributeTargetingTagHelper).Length -1),
- typeNameIdentifier: nameof(MultiAttributeAttributeTargetingTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "MultiAttributeAttributeTargetingTagHelper",
ruleBuilders: new Action[]
{
builder => builder.RequireAttributeDescriptor(attribute => attribute.Name("custom")),
@@ -844,52 +837,52 @@ public static TheoryData AttributeTargetData
})
},
{
- typeof(InheritedAttributeTargetingTagHelper),
+ "TestNamespace.InheritedAttributeTargetingTagHelper",
CreateTagHelperDescriptor(
TagHelperMatchingConventions.ElementCatchAllName,
- typeof(InheritedAttributeTargetingTagHelper).FullName,
+ "TestNamespace.InheritedAttributeTargetingTagHelper",
AssemblyName,
- typeNamespace: typeof(InheritedAttributeTargetingTagHelper).FullName.Substring(0, typeof(InheritedAttributeTargetingTagHelper).FullName.Length - nameof(InheritedAttributeTargetingTagHelper).Length -1),
- typeNameIdentifier: nameof(InheritedAttributeTargetingTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "InheritedAttributeTargetingTagHelper",
ruleBuilders: new Action[]
{
builder => builder.RequireAttributeDescriptor(attribute => attribute.Name("style")),
})
},
{
- typeof(RequiredAttributeTagHelper),
+ "TestNamespace.RequiredAttributeTagHelper",
CreateTagHelperDescriptor(
"input",
- typeof(RequiredAttributeTagHelper).FullName,
+ "TestNamespace.RequiredAttributeTagHelper",
AssemblyName,
- typeNamespace: typeof(RequiredAttributeTagHelper).FullName.Substring(0, typeof(RequiredAttributeTagHelper).FullName.Length - nameof(RequiredAttributeTagHelper).Length -1),
- typeNameIdentifier: nameof(RequiredAttributeTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "RequiredAttributeTagHelper",
ruleBuilders: new Action[]
{
builder => builder.RequireAttributeDescriptor(attribute => attribute.Name("class")),
})
},
{
- typeof(InheritedRequiredAttributeTagHelper),
+ "TestNamespace.InheritedRequiredAttributeTagHelper",
CreateTagHelperDescriptor(
"div",
- typeof(InheritedRequiredAttributeTagHelper).FullName,
+ "TestNamespace.InheritedRequiredAttributeTagHelper",
AssemblyName,
- typeNamespace: typeof(InheritedRequiredAttributeTagHelper).FullName.Substring(0, typeof(InheritedRequiredAttributeTagHelper).FullName.Length - nameof(InheritedRequiredAttributeTagHelper).Length -1),
- typeNameIdentifier: nameof(InheritedRequiredAttributeTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "InheritedRequiredAttributeTagHelper",
ruleBuilders: new Action[]
{
builder => builder.RequireAttributeDescriptor(attribute => attribute.Name("class")),
})
},
{
- typeof(MultiAttributeRequiredAttributeTagHelper),
+ "TestNamespace.MultiAttributeRequiredAttributeTagHelper",
CreateTagHelperDescriptor(
"div",
- typeof(MultiAttributeRequiredAttributeTagHelper).FullName,
+ "TestNamespace.MultiAttributeRequiredAttributeTagHelper",
AssemblyName,
- typeNamespace: typeof(MultiAttributeRequiredAttributeTagHelper).FullName.Substring(0, typeof(MultiAttributeRequiredAttributeTagHelper).FullName.Length - nameof(MultiAttributeRequiredAttributeTagHelper).Length -1),
- typeNameIdentifier: nameof(MultiAttributeRequiredAttributeTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "MultiAttributeRequiredAttributeTagHelper",
ruleBuilders: new Action[]
{
builder => builder
@@ -901,13 +894,13 @@ public static TheoryData AttributeTargetData
})
},
{
- typeof(MultiAttributeSameTagRequiredAttributeTagHelper),
+ "TestNamespace.MultiAttributeSameTagRequiredAttributeTagHelper",
CreateTagHelperDescriptor(
"input",
- typeof(MultiAttributeSameTagRequiredAttributeTagHelper).FullName,
+ "TestNamespace.MultiAttributeSameTagRequiredAttributeTagHelper",
AssemblyName,
- typeNamespace: typeof(MultiAttributeSameTagRequiredAttributeTagHelper).FullName.Substring(0, typeof(MultiAttributeSameTagRequiredAttributeTagHelper).FullName.Length - nameof(MultiAttributeSameTagRequiredAttributeTagHelper).Length -1),
- typeNameIdentifier: nameof(MultiAttributeSameTagRequiredAttributeTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "MultiAttributeSameTagRequiredAttributeTagHelper",
ruleBuilders: new Action[]
{
builder => builder.RequireAttributeDescriptor(attribute => attribute.Name("style")),
@@ -915,13 +908,13 @@ public static TheoryData AttributeTargetData
})
},
{
- typeof(MultiRequiredAttributeTagHelper),
+ "TestNamespace.MultiRequiredAttributeTagHelper",
CreateTagHelperDescriptor(
"input",
- typeof(MultiRequiredAttributeTagHelper).FullName,
+ "TestNamespace.MultiRequiredAttributeTagHelper",
AssemblyName,
- typeNamespace: typeof(MultiRequiredAttributeTagHelper).FullName.Substring(0, typeof(MultiRequiredAttributeTagHelper).FullName.Length - nameof(MultiRequiredAttributeTagHelper).Length -1),
- typeNameIdentifier: nameof(MultiRequiredAttributeTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "MultiRequiredAttributeTagHelper",
ruleBuilders: new Action[]
{
builder => builder
@@ -930,13 +923,13 @@ public static TheoryData AttributeTargetData
})
},
{
- typeof(MultiTagMultiRequiredAttributeTagHelper),
+ "TestNamespace.MultiTagMultiRequiredAttributeTagHelper",
CreateTagHelperDescriptor(
"div",
- typeof(MultiTagMultiRequiredAttributeTagHelper).FullName,
+ "TestNamespace.MultiTagMultiRequiredAttributeTagHelper",
AssemblyName,
- typeNamespace: typeof(MultiTagMultiRequiredAttributeTagHelper).FullName.Substring(0, typeof(MultiTagMultiRequiredAttributeTagHelper).FullName.Length - nameof(MultiTagMultiRequiredAttributeTagHelper).Length -1),
- typeNameIdentifier: nameof(MultiTagMultiRequiredAttributeTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "MultiTagMultiRequiredAttributeTagHelper",
ruleBuilders: new Action[]
{
builder => builder
@@ -950,13 +943,13 @@ public static TheoryData AttributeTargetData
})
},
{
- typeof(AttributeWildcardTargetingTagHelper),
+ "TestNamespace.AttributeWildcardTargetingTagHelper",
CreateTagHelperDescriptor(
TagHelperMatchingConventions.ElementCatchAllName,
- typeof(AttributeWildcardTargetingTagHelper).FullName,
+ "TestNamespace.AttributeWildcardTargetingTagHelper",
AssemblyName,
- typeNamespace: typeof(AttributeWildcardTargetingTagHelper).FullName.Substring(0, typeof(AttributeWildcardTargetingTagHelper).FullName.Length - nameof(AttributeWildcardTargetingTagHelper).Length -1),
- typeNameIdentifier: nameof(AttributeWildcardTargetingTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "AttributeWildcardTargetingTagHelper",
ruleBuilders: new Action[]
{
builder => builder
@@ -966,13 +959,13 @@ public static TheoryData AttributeTargetData
})
},
{
- typeof(MultiAttributeWildcardTargetingTagHelper),
+ "TestNamespace.MultiAttributeWildcardTargetingTagHelper",
CreateTagHelperDescriptor(
TagHelperMatchingConventions.ElementCatchAllName,
- typeof(MultiAttributeWildcardTargetingTagHelper).FullName,
+ "TestNamespace.MultiAttributeWildcardTargetingTagHelper",
AssemblyName,
- typeNamespace: typeof(MultiAttributeWildcardTargetingTagHelper).FullName.Substring(0, typeof(MultiAttributeWildcardTargetingTagHelper).FullName.Length - nameof(MultiAttributeWildcardTargetingTagHelper).Length -1),
- typeNameIdentifier: nameof(MultiAttributeWildcardTargetingTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "MultiAttributeWildcardTargetingTagHelper",
ruleBuilders: new Action[]
{
builder => builder
@@ -991,12 +984,12 @@ public static TheoryData AttributeTargetData
[Theory]
[MemberData(nameof(AttributeTargetData))]
public void CreateDescriptor_ReturnsExpectedDescriptors(
- Type tagHelperType,
+ string tagHelperTypeFullName,
TagHelperDescriptor expectedDescriptor)
{
// Arrange
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperType.FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperTypeFullName);
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1010,16 +1003,16 @@ public static TheoryData HtmlCaseData
get
{
// tagHelperType, expectedTagName, expectedAttributeName
- return new TheoryData
+ return new TheoryData
{
- { typeof(SingleAttributeTagHelper), "single-attribute", "int-attribute" },
- { typeof(ALLCAPSTAGHELPER), "allcaps", "allcapsattribute" },
- { typeof(CAPSOnOUTSIDETagHelper), "caps-on-outside", "caps-on-outsideattribute" },
- { typeof(capsONInsideTagHelper), "caps-on-inside", "caps-on-insideattribute" },
- { typeof(One1Two2Three3TagHelper), "one1-two2-three3", "one1-two2-three3-attribute" },
- { typeof(ONE1TWO2THREE3TagHelper), "one1two2three3", "one1two2three3-attribute" },
- { typeof(First_Second_ThirdHiTagHelper), "first_second_third-hi", "first_second_third-attribute" },
- { typeof(UNSuffixedCLASS), "un-suffixed-class", "un-suffixed-attribute" },
+ { "TestNamespace.SingleAttributeTagHelper", "single-attribute", "int-attribute" },
+ { "TestNamespace.ALLCAPSTAGHELPER", "allcaps", "allcapsattribute" },
+ { "TestNamespace.CAPSOnOUTSIDETagHelper", "caps-on-outside", "caps-on-outsideattribute" },
+ { "TestNamespace.capsONInsideTagHelper", "caps-on-inside", "caps-on-insideattribute" },
+ { "TestNamespace.One1Two2Three3TagHelper", "one1-two2-three3", "one1-two2-three3-attribute" },
+ { "TestNamespace.ONE1TWO2THREE3TagHelper", "one1two2three3", "one1two2three3-attribute" },
+ { "TestNamespace.First_Second_ThirdHiTagHelper", "first_second_third-hi", "first_second_third-attribute" },
+ { "TestNamespace.UNSuffixedCLASS", "un-suffixed-class", "un-suffixed-attribute" },
};
}
}
@@ -1027,13 +1020,13 @@ public static TheoryData HtmlCaseData
[Theory]
[MemberData(nameof(HtmlCaseData))]
public void CreateDescriptor_HtmlCasesTagNameAndAttributeName(
- Type tagHelperType,
+ string tagHelperTypeFullName,
string expectedTagName,
string expectedAttributeName)
{
// Arrange
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperType.FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName(tagHelperTypeFullName);
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1049,30 +1042,26 @@ public void CreateDescriptor_HtmlCasesTagNameAndAttributeName(
public void CreateDescriptor_OverridesAttributeNameFromAttribute()
{
// Arrange
- var validProperty1 = typeof(OverriddenAttributeTagHelper).GetProperty(
- nameof(OverriddenAttributeTagHelper.ValidAttribute1));
- var validProperty2 = typeof(OverriddenAttributeTagHelper).GetProperty(
- nameof(OverriddenAttributeTagHelper.ValidAttribute2));
var expectedDescriptor =
CreateTagHelperDescriptor(
"overridden-attribute",
- typeof(OverriddenAttributeTagHelper).FullName,
+ "TestNamespace.OverriddenAttributeTagHelper",
AssemblyName,
- typeNamespace: typeof(OverriddenAttributeTagHelper).FullName.Substring(0, typeof(OverriddenAttributeTagHelper).FullName.Length - nameof(OverriddenAttributeTagHelper).Length -1),
- typeNameIdentifier: nameof(OverriddenAttributeTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "OverriddenAttributeTagHelper",
new Action[]
{
builder => builder
.Name("SomethingElse")
- .Metadata(PropertyName(validProperty1.Name))
- .TypeName(validProperty1.PropertyType.FullName),
+ .Metadata(PropertyName("ValidAttribute1"))
+ .TypeName(typeof(string).FullName),
builder => builder
.Name("Something-Else")
- .Metadata(PropertyName(validProperty2.Name))
- .TypeName(validProperty2.PropertyType.FullName),
+ .Metadata(PropertyName("ValidAttribute2"))
+ .TypeName(typeof(string).FullName),
});
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(typeof(OverriddenAttributeTagHelper).FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName("TestNamespace.OverriddenAttributeTagHelper");
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1085,30 +1074,26 @@ public void CreateDescriptor_OverridesAttributeNameFromAttribute()
public void CreateDescriptor_DoesNotInheritOverridenAttributeName()
{
// Arrange
- var validProperty1 = typeof(InheritedOverriddenAttributeTagHelper).GetProperty(
- nameof(InheritedOverriddenAttributeTagHelper.ValidAttribute1));
- var validProperty2 = typeof(InheritedOverriddenAttributeTagHelper).GetProperty(
- nameof(InheritedOverriddenAttributeTagHelper.ValidAttribute2));
var expectedDescriptor =
CreateTagHelperDescriptor(
"inherited-overridden-attribute",
- typeof(InheritedOverriddenAttributeTagHelper).FullName,
+ "TestNamespace.InheritedOverriddenAttributeTagHelper",
AssemblyName,
- typeNamespace: typeof(InheritedOverriddenAttributeTagHelper).FullName.Substring(0, typeof(InheritedOverriddenAttributeTagHelper).FullName.Length - nameof(InheritedOverriddenAttributeTagHelper).Length -1),
- typeNameIdentifier: nameof(InheritedOverriddenAttributeTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "InheritedOverriddenAttributeTagHelper",
new Action[]
{
builder => builder
.Name("valid-attribute1")
- .Metadata(PropertyName(validProperty1.Name))
- .TypeName(validProperty1.PropertyType.FullName),
+ .Metadata(PropertyName("ValidAttribute1"))
+ .TypeName(typeof(string).FullName),
builder => builder
.Name("Something-Else")
- .Metadata(PropertyName(validProperty2.Name))
- .TypeName(validProperty2.PropertyType.FullName),
+ .Metadata(PropertyName("ValidAttribute2"))
+ .TypeName(typeof(string).FullName),
});
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(typeof(InheritedOverriddenAttributeTagHelper).FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName("TestNamespace.InheritedOverriddenAttributeTagHelper");
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1121,30 +1106,25 @@ public void CreateDescriptor_DoesNotInheritOverridenAttributeName()
public void CreateDescriptor_AllowsOverriddenAttributeNameOnUnimplementedVirtual()
{
// Arrange
- var validProperty1 = typeof(InheritedNotOverriddenAttributeTagHelper).GetProperty(
- nameof(InheritedNotOverriddenAttributeTagHelper.ValidAttribute1));
- var validProperty2 = typeof(InheritedNotOverriddenAttributeTagHelper).GetProperty(
- nameof(InheritedNotOverriddenAttributeTagHelper.ValidAttribute2));
-
var expectedDescriptor = CreateTagHelperDescriptor(
"inherited-not-overridden-attribute",
- typeof(InheritedNotOverriddenAttributeTagHelper).FullName,
+ "TestNamespace.InheritedNotOverriddenAttributeTagHelper",
AssemblyName,
- typeNamespace: typeof(InheritedNotOverriddenAttributeTagHelper).FullName.Substring(0, typeof(InheritedNotOverriddenAttributeTagHelper).FullName.Length - nameof(InheritedNotOverriddenAttributeTagHelper).Length -1),
- typeNameIdentifier: nameof(InheritedNotOverriddenAttributeTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "InheritedNotOverriddenAttributeTagHelper",
new Action[]
{
builder => builder
.Name("SomethingElse")
- .Metadata(PropertyName(validProperty1.Name))
- .TypeName(validProperty1.PropertyType.FullName),
+ .Metadata(PropertyName("ValidAttribute1"))
+ .TypeName(typeof(string).FullName),
builder => builder
.Name("Something-Else")
- .Metadata(PropertyName(validProperty2.Name))
- .TypeName(validProperty2.PropertyType.FullName),
+ .Metadata(PropertyName("ValidAttribute2"))
+ .TypeName(typeof(string).FullName),
});
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(typeof(InheritedNotOverriddenAttributeTagHelper).FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName("TestNamespace.InheritedNotOverriddenAttributeTagHelper");
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1159,19 +1139,19 @@ public void CreateDescriptor_BuildsDescriptorsWithInheritedProperties()
// Arrange
var expectedDescriptor = CreateTagHelperDescriptor(
"inherited-single-attribute",
- typeof(InheritedSingleAttributeTagHelper).FullName,
+ "TestNamespace.InheritedSingleAttributeTagHelper",
AssemblyName,
- typeNamespace: typeof(InheritedSingleAttributeTagHelper).FullName.Substring(0, typeof(InheritedSingleAttributeTagHelper).FullName.Length - nameof(InheritedSingleAttributeTagHelper).Length -1),
- typeNameIdentifier: nameof(InheritedSingleAttributeTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "InheritedSingleAttributeTagHelper",
new Action[]
{
builder => builder
.Name("int-attribute")
- .Metadata(PropertyName(nameof(InheritedSingleAttributeTagHelper.IntAttribute)))
+ .Metadata(PropertyName("IntAttribute"))
.TypeName(typeof(int).FullName)
});
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(typeof(InheritedSingleAttributeTagHelper).FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName("TestNamespace.InheritedSingleAttributeTagHelper");
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1184,22 +1164,21 @@ public void CreateDescriptor_BuildsDescriptorsWithInheritedProperties()
public void CreateDescriptor_BuildsDescriptorsWithConventionNames()
{
// Arrange
- var intProperty = typeof(SingleAttributeTagHelper).GetProperty(nameof(SingleAttributeTagHelper.IntAttribute));
var expectedDescriptor = CreateTagHelperDescriptor(
"single-attribute",
- typeof(SingleAttributeTagHelper).FullName,
+ "TestNamespace.SingleAttributeTagHelper",
AssemblyName,
- typeNamespace: typeof(SingleAttributeTagHelper).FullName.Substring(0, typeof(SingleAttributeTagHelper).FullName.Length - nameof(SingleAttributeTagHelper).Length -1),
- typeNameIdentifier: nameof(SingleAttributeTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "SingleAttributeTagHelper",
new Action[]
{
builder => builder
.Name("int-attribute")
- .Metadata(PropertyName(intProperty.Name))
- .TypeName(intProperty.PropertyType.FullName)
+ .Metadata(PropertyName("IntAttribute"))
+ .TypeName(typeof(int).FullName)
});
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(typeof(SingleAttributeTagHelper).FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName("TestNamespace.SingleAttributeTagHelper");
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1212,23 +1191,21 @@ public void CreateDescriptor_BuildsDescriptorsWithConventionNames()
public void CreateDescriptor_OnlyAcceptsPropertiesWithGetAndSet()
{
// Arrange
- var validProperty = typeof(MissingAccessorTagHelper).GetProperty(
- nameof(MissingAccessorTagHelper.ValidAttribute));
var expectedDescriptor = CreateTagHelperDescriptor(
"missing-accessor",
- typeof(MissingAccessorTagHelper).FullName,
+ "TestNamespace.MissingAccessorTagHelper",
AssemblyName,
- typeNamespace: typeof(MissingAccessorTagHelper).FullName.Substring(0, typeof(MissingAccessorTagHelper).FullName.Length - nameof(MissingAccessorTagHelper).Length -1),
- typeNameIdentifier: nameof(MissingAccessorTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "MissingAccessorTagHelper",
new Action[]
{
builder => builder
.Name("valid-attribute")
- .Metadata(PropertyName(validProperty.Name))
- .TypeName(validProperty.PropertyType.FullName)
+ .Metadata(PropertyName("ValidAttribute"))
+ .TypeName(typeof(string).FullName)
});
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(typeof(MissingAccessorTagHelper).FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName("TestNamespace.MissingAccessorTagHelper");
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1241,23 +1218,21 @@ public void CreateDescriptor_OnlyAcceptsPropertiesWithGetAndSet()
public void CreateDescriptor_OnlyAcceptsPropertiesWithPublicGetAndSet()
{
// Arrange
- var validProperty = typeof(NonPublicAccessorTagHelper).GetProperty(
- nameof(NonPublicAccessorTagHelper.ValidAttribute));
var expectedDescriptor = CreateTagHelperDescriptor(
"non-public-accessor",
- typeof(NonPublicAccessorTagHelper).FullName,
+ "TestNamespace.NonPublicAccessorTagHelper",
AssemblyName,
- typeNamespace: typeof(NonPublicAccessorTagHelper).FullName.Substring(0, typeof(NonPublicAccessorTagHelper).FullName.Length - nameof(NonPublicAccessorTagHelper).Length -1),
- typeNameIdentifier: nameof(NonPublicAccessorTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "NonPublicAccessorTagHelper",
new Action[]
{
builder => builder
.Name("valid-attribute")
- .Metadata(PropertyName(validProperty.Name))
- .TypeName(validProperty.PropertyType.FullName)
+ .Metadata(PropertyName("ValidAttribute"))
+ .TypeName(typeof(string).FullName)
});
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(typeof(NonPublicAccessorTagHelper).FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName("TestNamespace.NonPublicAccessorTagHelper");
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1272,19 +1247,19 @@ public void CreateDescriptor_DoesNotIncludePropertiesWithNotBound()
// Arrange
var expectedDescriptor = CreateTagHelperDescriptor(
"not-bound-attribute",
- typeof(NotBoundAttributeTagHelper).FullName,
+ "TestNamespace.NotBoundAttributeTagHelper",
AssemblyName,
- typeNamespace: typeof(NotBoundAttributeTagHelper).FullName.Substring(0, typeof(NotBoundAttributeTagHelper).FullName.Length - nameof(NotBoundAttributeTagHelper).Length -1),
- typeNameIdentifier: nameof(NotBoundAttributeTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "NotBoundAttributeTagHelper",
new Action[]
{
builder => builder
.Name("bound-property")
- .Metadata(PropertyName(nameof(NotBoundAttributeTagHelper.BoundProperty)))
+ .Metadata(PropertyName("BoundProperty"))
.TypeName(typeof(object).FullName)
});
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(typeof(NotBoundAttributeTagHelper).FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName("TestNamespace.NotBoundAttributeTagHelper");
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1300,15 +1275,15 @@ public void CreateDescriptor_ResolvesMultipleTagHelperDescriptorsFromSingleType(
var expectedDescriptor =
CreateTagHelperDescriptor(
string.Empty,
- typeof(MultiTagTagHelper).FullName,
+ "TestNamespace.MultiTagTagHelper",
AssemblyName,
- typeNamespace: typeof(MultiTagTagHelper).FullName.Substring(0, typeof(MultiTagTagHelper).FullName.Length - nameof(MultiTagTagHelper).Length -1),
- typeNameIdentifier: nameof(MultiTagTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "MultiTagTagHelper",
new Action[]
{
builder => builder
.Name("valid-attribute")
- .Metadata(PropertyName(nameof(MultiTagTagHelper.ValidAttribute)))
+ .Metadata(PropertyName("ValidAttribute"))
.TypeName(typeof(string).FullName),
},
new Action[]
@@ -1317,7 +1292,7 @@ public void CreateDescriptor_ResolvesMultipleTagHelperDescriptorsFromSingleType(
builder => builder.RequireTagName("div"),
});
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(typeof(MultiTagTagHelper).FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName("TestNamespace.MultiTagTagHelper");
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1330,22 +1305,21 @@ public void CreateDescriptor_ResolvesMultipleTagHelperDescriptorsFromSingleType(
public void CreateDescriptor_DoesNotResolveInheritedTagNames()
{
// Arrange
- var validProp = typeof(InheritedMultiTagTagHelper).GetProperty(nameof(InheritedMultiTagTagHelper.ValidAttribute));
var expectedDescriptor = CreateTagHelperDescriptor(
"inherited-multi-tag",
- typeof(InheritedMultiTagTagHelper).FullName,
+ "TestNamespace.InheritedMultiTagTagHelper",
AssemblyName,
- typeNamespace: typeof(InheritedMultiTagTagHelper).FullName.Substring(0, typeof(InheritedMultiTagTagHelper).FullName.Length - nameof(InheritedMultiTagTagHelper).Length -1),
- typeNameIdentifier: nameof(InheritedMultiTagTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "InheritedMultiTagTagHelper",
new Action[]
{
builder => builder
.Name("valid-attribute")
- .Metadata(PropertyName(validProp.Name))
- .TypeName(validProp.PropertyType.FullName),
+ .Metadata(PropertyName("ValidAttribute"))
+ .TypeName(typeof(string).FullName),
});
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(typeof(InheritedMultiTagTagHelper).FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName("TestNamespace.InheritedMultiTagTagHelper");
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1360,10 +1334,10 @@ public void CreateDescriptor_IgnoresDuplicateTagNamesFromAttribute()
// Arrange
var expectedDescriptor = CreateTagHelperDescriptor(
string.Empty,
- typeof(DuplicateTagNameTagHelper).FullName,
+ "TestNamespace.DuplicateTagNameTagHelper",
AssemblyName,
- typeNamespace: typeof(DuplicateTagNameTagHelper).FullName.Substring(0, typeof(DuplicateTagNameTagHelper).FullName.Length - nameof(DuplicateTagNameTagHelper).Length -1),
- typeNameIdentifier: nameof(DuplicateTagNameTagHelper),
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "DuplicateTagNameTagHelper",
ruleBuilders: new Action[]
{
builder => builder.RequireTagName("p"),
@@ -1371,7 +1345,7 @@ public void CreateDescriptor_IgnoresDuplicateTagNamesFromAttribute()
});
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(typeof(DuplicateTagNameTagHelper).FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName("TestNamespace.DuplicateTagNameTagHelper");
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1387,12 +1361,12 @@ public void CreateDescriptor_OverridesTagNameFromAttribute()
var expectedDescriptor =
CreateTagHelperDescriptor(
"data-condition",
- typeof(OverrideNameTagHelper).FullName,
+ "TestNamespace.OverrideNameTagHelper",
AssemblyName,
- typeNamespace: typeof(OverrideNameTagHelper).FullName.Substring(0, typeof(OverrideNameTagHelper).FullName.Length - nameof(OverrideNameTagHelper).Length -1),
- typeNameIdentifier: nameof(OverrideNameTagHelper));
+ typeNamespace: "TestNamespace",
+ typeNameIdentifier: "OverrideNameTagHelper");
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(typeof(OverrideNameTagHelper).FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName("TestNamespace.OverrideNameTagHelper");
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1425,13 +1399,13 @@ public void CreateDescriptor_CreatesErrorOnInvalidNames(
// Arrange
name = name.Replace("\n", "\\n").Replace("\r", "\\r").Replace("\"", "\\\"");
var text = $$"""
- [{{typeof(AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute).FullName}}("{{name}}")]
- public class DynamicTestTagHelper : {{typeof(AspNetCore.Razor.TagHelpers.TagHelper).FullName}}
+ [Microsoft.AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute("{{name}}")]
+ public class DynamicTestTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
{
}
""";
- var syntaxTree = CSharpSyntaxTree.ParseText(text);
- var compilation = TestCompilation.Create(_assembly, syntaxTree);
+ var syntaxTree = Parse(text);
+ var compilation = Compilation.AddSyntaxTrees(syntaxTree);
var tagHelperType = compilation.GetTypeByMetadataName("DynamicTestTagHelper");
var attribute = tagHelperType.GetAttributes().Single();
var factory = new DefaultTagHelperDescriptorFactory(compilation, includeDocumentation: false, excludeHidden: false);
@@ -1477,80 +1451,80 @@ public static TheoryData InvalidTagHelperAttributeDescriptorData
{
get
{
- var invalidBoundAttributeBuilder = new TagHelperDescriptorBuilder(TagHelperConventions.DefaultKind, nameof(InvalidBoundAttribute), "Test");
- invalidBoundAttributeBuilder.Metadata(TypeName(typeof(InvalidBoundAttribute).FullName));
+ var invalidBoundAttributeBuilder = new TagHelperDescriptorBuilder(TagHelperConventions.DefaultKind, "InvalidBoundAttribute", "Test");
+ invalidBoundAttributeBuilder.Metadata(TypeName("TestNamespace.InvalidBoundAttribute"));
// type, expectedAttributeDescriptors
- return new TheoryData>
+ return new TheoryData>
{
{
- typeof(InvalidBoundAttribute),
+ "TestNamespace.InvalidBoundAttribute",
new[]
{
- CreateAttributeFor(typeof(InvalidBoundAttribute), attribute =>
+ CreateAttributeFor("TestNamespace.InvalidBoundAttribute", attribute =>
{
attribute
.Name("data-something")
- .Metadata(PropertyName(nameof(InvalidBoundAttribute.DataSomething)))
+ .Metadata(PropertyName("DataSomething"))
.TypeName(typeof(string).FullName);
}),
}
},
{
- typeof(InvalidBoundAttributeWithValid),
+ "TestNamespace.InvalidBoundAttributeWithValid",
new[]
{
- CreateAttributeFor(typeof(InvalidBoundAttributeWithValid), attribute =>
+ CreateAttributeFor("TestNamespace.InvalidBoundAttributeWithValid", attribute =>
{
attribute
.Name("data-something")
- .Metadata(PropertyName(nameof(InvalidBoundAttributeWithValid.DataSomething)))
+ .Metadata(PropertyName("DataSomething"))
.TypeName(typeof(string).FullName); ;
}),
- CreateAttributeFor(typeof(InvalidBoundAttributeWithValid), attribute =>
+ CreateAttributeFor("TestNamespace.InvalidBoundAttributeWithValid", attribute =>
{
attribute
.Name("int-attribute")
- .Metadata(PropertyName(nameof(InvalidBoundAttributeWithValid.IntAttribute)))
+ .Metadata(PropertyName("IntAttribute"))
.TypeName(typeof(int).FullName);
}),
}
},
{
- typeof(OverriddenInvalidBoundAttributeWithValid),
+ "TestNamespace.OverriddenInvalidBoundAttributeWithValid",
new[]
{
- CreateAttributeFor(typeof(OverriddenInvalidBoundAttributeWithValid), attribute =>
+ CreateAttributeFor("TestNamespace.OverriddenInvalidBoundAttributeWithValid", attribute =>
{
attribute
.Name("valid-something")
- .Metadata(PropertyName(nameof(OverriddenInvalidBoundAttributeWithValid.DataSomething)))
+ .Metadata(PropertyName("DataSomething"))
.TypeName(typeof(string).FullName);
}),
}
},
{
- typeof(OverriddenValidBoundAttributeWithInvalid),
+ "TestNamespace.OverriddenValidBoundAttributeWithInvalid",
new[]
{
- CreateAttributeFor(typeof(OverriddenValidBoundAttributeWithInvalid), attribute =>
+ CreateAttributeFor("TestNamespace.OverriddenValidBoundAttributeWithInvalid", attribute =>
{
attribute
.Name("data-something")
- .Metadata(PropertyName(nameof(OverriddenValidBoundAttributeWithInvalid.ValidSomething)))
+ .Metadata(PropertyName("ValidSomething"))
.TypeName(typeof(string).FullName);
}),
}
},
{
- typeof(OverriddenValidBoundAttributeWithInvalidUpperCase),
+ "TestNamespace.OverriddenValidBoundAttributeWithInvalidUpperCase",
new[]
{
- CreateAttributeFor(typeof(OverriddenValidBoundAttributeWithInvalidUpperCase), attribute =>
+ CreateAttributeFor("TestNamespace.OverriddenValidBoundAttributeWithInvalidUpperCase", attribute =>
{
attribute
.Name("DATA-SOMETHING")
- .Metadata(PropertyName(nameof(OverriddenValidBoundAttributeWithInvalidUpperCase.ValidSomething)))
+ .Metadata(PropertyName("ValidSomething"))
.TypeName(typeof(string).FullName);
}),
}
@@ -1562,12 +1536,12 @@ public static TheoryData InvalidTagHelperAttributeDescriptorData
[Theory]
[MemberData(nameof(InvalidTagHelperAttributeDescriptorData))]
public void CreateDescriptor_DoesNotAllowDataDashAttributes(
- Type type,
+ string typeFullName,
IEnumerable expectedAttributeDescriptors)
{
// Arrange
var factory = new DefaultTagHelperDescriptorFactory(Compilation, includeDocumentation: false, excludeHidden: false);
- var typeSymbol = Compilation.GetTypeByMetadataName(type.FullName);
+ var typeSymbol = Compilation.GetTypeByMetadataName(typeFullName);
// Act
var descriptor = factory.CreateDescriptor(typeSymbol);
@@ -1605,14 +1579,14 @@ public void CreateDescriptor_WithValidAttributeName_HasNoErrors(string name)
{
// Arrange
var text = $$"""
- public class DynamicTestTagHelper : {{typeof(AspNetCore.Razor.TagHelpers.TagHelper).FullName}}
+ public class DynamicTestTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
{
- [{{typeof(AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute).FullName}}("{{name}}")]
+ [Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute("{{name}}")]
public string SomeAttribute { get; set; }
}
""";
- var syntaxTree = CSharpSyntaxTree.ParseText(text);
- var compilation = TestCompilation.Create(_assembly, syntaxTree);
+ var syntaxTree = Parse(text);
+ var compilation = Compilation.AddSyntaxTrees(syntaxTree);
var tagHelperType = compilation.GetTypeByMetadataName("DynamicTestTagHelper");
var factory = new DefaultTagHelperDescriptorFactory(compilation, includeDocumentation: false, excludeHidden: false);
@@ -1646,14 +1620,14 @@ public void CreateDescriptor_WithValidAttributePrefix_HasNoErrors(string prefix)
{
// Arrange
var text = $$"""
- public class DynamicTestTagHelper : {{typeof(AspNetCore.Razor.TagHelpers.TagHelper).FullName}}
+ public class DynamicTestTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
{
- [{{typeof(AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute).FullName}}({{nameof(AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute.DictionaryAttributePrefix)}} = "{{prefix}}")]
+ [Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute(DictionaryAttributePrefix = "{{prefix}}")]
public System.Collections.Generic.IDictionary SomeAttribute { get; set; }
}
""";
- var syntaxTree = CSharpSyntaxTree.ParseText(text);
- var compilation = TestCompilation.Create(_assembly, syntaxTree);
+ var syntaxTree = Parse(text);
+ var compilation = Compilation.AddSyntaxTrees(syntaxTree);
var tagHelperType = compilation.GetTypeByMetadataName("DynamicTestTagHelper");
var factory = new DefaultTagHelperDescriptorFactory(compilation, includeDocumentation: false, excludeHidden: false);
@@ -1690,14 +1664,14 @@ public void CreateDescriptor_WithInvalidAttributeName_HasErrors(string name, str
// Arrange
name = name.Replace("\n", "\\n").Replace("\r", "\\r").Replace("\"", "\\\"");
var text = $$"""
- public class DynamicTestTagHelper : {{typeof(AspNetCore.Razor.TagHelpers.TagHelper).FullName}}
+ public class DynamicTestTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
{
- [{{typeof(AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute).FullName}}("{{name}}")]
+ [Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute("{{name}}")]
public string InvalidProperty { get; set; }
}
""";
- var syntaxTree = CSharpSyntaxTree.ParseText(text);
- var compilation = TestCompilation.Create(_assembly, syntaxTree);
+ var syntaxTree = Parse(text);
+ var compilation = Compilation.AddSyntaxTrees(syntaxTree);
var tagHelperType = compilation.GetTypeByMetadataName("DynamicTestTagHelper");
var factory = new DefaultTagHelperDescriptorFactory(compilation, includeDocumentation: false, excludeHidden: false);
@@ -1737,14 +1711,14 @@ public void CreateDescriptor_WithInvalidAttributePrefix_HasErrors(string prefix,
// Arrange
prefix = prefix.Replace("\n", "\\n").Replace("\r", "\\r").Replace("\"", "\\\"");
var text = $$"""
- public class DynamicTestTagHelper : {{typeof(AspNetCore.Razor.TagHelpers.TagHelper).FullName}}
+ public class DynamicTestTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
{
- [{{typeof(AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute).FullName}}({{nameof(AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute.DictionaryAttributePrefix)}} = "{{prefix}}")]
+ [Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute(DictionaryAttributePrefix = "{{prefix}}")]
public System.Collections.Generic.IDictionary InvalidProperty { get; set; }
}
""";
- var syntaxTree = CSharpSyntaxTree.ParseText(text);
- var compilation = TestCompilation.Create(_assembly, syntaxTree);
+ var syntaxTree = Parse(text);
+ var compilation = Compilation.AddSyntaxTrees(syntaxTree);
var tagHelperType = compilation.GetTypeByMetadataName("DynamicTestTagHelper");
var factory = new DefaultTagHelperDescriptorFactory(compilation, includeDocumentation: false, excludeHidden: false);
@@ -1781,13 +1755,13 @@ public void CreateDescriptor_WithInvalidAllowedChildren_HasErrors(string name, s
// Arrange
name = name.Replace("\n", "\\n").Replace("\r", "\\r").Replace("\"", "\\\"");
var text = $$"""
- [{{typeof(AspNetCore.Razor.TagHelpers.RestrictChildrenAttribute).FullName}}("{{name}}")]
- public class DynamicTestTagHelper : {{typeof(AspNetCore.Razor.TagHelpers.TagHelper).FullName}}
+ [Microsoft.AspNetCore.Razor.TagHelpers.RestrictChildrenAttribute("{{name}}")]
+ public class DynamicTestTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
{
}
""";
- var syntaxTree = CSharpSyntaxTree.ParseText(text);
- var compilation = TestCompilation.Create(_assembly, syntaxTree);
+ var syntaxTree = Parse(text);
+ var compilation = Compilation.AddSyntaxTrees(syntaxTree);
var tagHelperType = compilation.GetTypeByMetadataName("DynamicTestTagHelper");
var factory = new DefaultTagHelperDescriptorFactory(compilation, includeDocumentation: false, excludeHidden: false);
@@ -1823,13 +1797,13 @@ public void CreateDescriptor_WithInvalidParentTag_HasErrors(string name, string[
// Arrange
name = name.Replace("\n", "\\n").Replace("\r", "\\r").Replace("\"", "\\\"");
var text = $$"""
- [{{typeof(AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute).FullName}}({{nameof(AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute.ParentTag)}} = "{{name}}")]
- public class DynamicTestTagHelper : {{typeof(AspNetCore.Razor.TagHelpers.TagHelper).FullName}}
+ [Microsoft.AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute(ParentTag = "{{name}}")]
+ public class DynamicTestTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
{
}
""";
- var syntaxTree = CSharpSyntaxTree.ParseText(text);
- var compilation = TestCompilation.Create(_assembly, syntaxTree);
+ var syntaxTree = Parse(text);
+ var compilation = Compilation.AddSyntaxTrees(syntaxTree);
var tagHelperType = compilation.GetTypeByMetadataName("DynamicTestTagHelper");
var factory = new DefaultTagHelperDescriptorFactory(compilation, includeDocumentation: false, excludeHidden: false);
@@ -1870,17 +1844,17 @@ public static TheoryData TagHelperWithPrefixData
dictionaryNamespace = dictionaryNamespace.Substring(0, dictionaryNamespace.IndexOf('`'));
// tagHelperType, expectedAttributeDescriptors, expectedDiagnostics
- return new TheoryData, IEnumerable>
+ return new TheoryData, IEnumerable>
{
{
- typeof(DefaultValidHtmlAttributePrefix),
+ "TestNamespace.DefaultValidHtmlAttributePrefix",
new[]
{
- CreateAttributeFor(typeof(DefaultValidHtmlAttributePrefix), attribute =>
+ CreateAttributeFor("TestNamespace.DefaultValidHtmlAttributePrefix", attribute =>
{
attribute
.Name("dictionary-property")
- .Metadata(PropertyName(nameof(DefaultValidHtmlAttributePrefix.DictionaryProperty)))
+ .Metadata(PropertyName("DictionaryProperty"))
.TypeName($"{dictionaryNamespace}")
.AsDictionaryAttribute("dictionary-property-", typeof(string).FullName);
}),
@@ -1888,14 +1862,14 @@ public static TheoryData TagHelperWithPrefixData
Enumerable.Empty()
},
{
- typeof(SingleValidHtmlAttributePrefix),
+ "TestNamespace.SingleValidHtmlAttributePrefix",
new[]
{
- CreateAttributeFor(typeof(SingleValidHtmlAttributePrefix), attribute =>
+ CreateAttributeFor("TestNamespace.SingleValidHtmlAttributePrefix", attribute =>
{
attribute
.Name("valid-name")
- .Metadata(PropertyName(nameof(SingleValidHtmlAttributePrefix.DictionaryProperty)))
+ .Metadata(PropertyName("DictionaryProperty"))
.TypeName($"{dictionaryNamespace}")
.AsDictionaryAttribute("valid-name-", typeof(string).FullName);
}),
@@ -1903,67 +1877,67 @@ public static TheoryData TagHelperWithPrefixData
Enumerable.Empty()
},
{
- typeof(MultipleValidHtmlAttributePrefix),
+ "TestNamespace.MultipleValidHtmlAttributePrefix",
new[]
{
- CreateAttributeFor(typeof(MultipleValidHtmlAttributePrefix), attribute =>
+ CreateAttributeFor("TestNamespace.MultipleValidHtmlAttributePrefix", attribute =>
{
attribute
.Name("valid-name1")
- .Metadata(PropertyName(nameof(MultipleValidHtmlAttributePrefix.DictionaryProperty)))
+ .Metadata(PropertyName("DictionaryProperty"))
.TypeName($"{typeof(Dictionary<,>).Namespace}.Dictionary")
.AsDictionaryAttribute("valid-prefix1-", typeof(object).FullName);
}),
- CreateAttributeFor(typeof(MultipleValidHtmlAttributePrefix), attribute =>
+ CreateAttributeFor("TestNamespace.MultipleValidHtmlAttributePrefix", attribute =>
{
attribute
.Name("valid-name2")
- .Metadata(PropertyName(nameof(MultipleValidHtmlAttributePrefix.DictionarySubclassProperty)))
- .TypeName(typeof(DictionarySubclass).FullName)
+ .Metadata(PropertyName("DictionarySubclassProperty"))
+ .TypeName("TestNamespace.DictionarySubclass")
.AsDictionaryAttribute("valid-prefix2-", typeof(string).FullName);
}),
- CreateAttributeFor(typeof(MultipleValidHtmlAttributePrefix), attribute =>
+ CreateAttributeFor("TestNamespace.MultipleValidHtmlAttributePrefix", attribute =>
{
attribute
.Name("valid-name3")
- .Metadata(PropertyName(nameof(MultipleValidHtmlAttributePrefix.DictionaryWithoutParameterlessConstructorProperty)))
- .TypeName(typeof(DictionaryWithoutParameterlessConstructor).FullName)
+ .Metadata(PropertyName("DictionaryWithoutParameterlessConstructorProperty"))
+ .TypeName("TestNamespace.DictionaryWithoutParameterlessConstructor")
.AsDictionaryAttribute("valid-prefix3-", typeof(string).FullName);
}),
- CreateAttributeFor(typeof(MultipleValidHtmlAttributePrefix), attribute =>
+ CreateAttributeFor("TestNamespace.MultipleValidHtmlAttributePrefix", attribute =>
{
attribute
.Name("valid-name4")
- .Metadata(PropertyName(nameof(MultipleValidHtmlAttributePrefix.GenericDictionarySubclassProperty)))
- .TypeName(typeof(GenericDictionarySubclass