Quick fixes from MVC

We're close to hooking up new Razor to MVC. This is a set of enabling
'quick fix' changes to resolve some blockers to using Razor.Evolution in
the product.

Main issues:
 - Types not public enough - anything in the .Legacy namespace is still
   slated from 'improvement'
 - Wrong references. We don't want .Workspaces in MVC, so moving the heavy
   lifting of TagHelper discovery to CodeAnalysis.Razor.
This commit is contained in:
Ryan Nowak 2017-01-24 09:22:28 -08:00
parent 3d5cfc8b8b
commit 03b63d97a2
64 changed files with 828 additions and 626 deletions

View File

@ -90,7 +90,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
_namespace.AddAfter<UsingStatementIRNode>(node);
}
internal override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
public override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
{
_class.Insert(0, node);
}

View File

@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
VisitDefault(node);
}
internal override void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
public override void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
{
// As a special case the TagHelperIRNode (which must be the parent) is the one that carries
// the location. The execute node won't have one, but the instrumentation goes around the call

View File

@ -201,7 +201,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
Context.Writer.WriteEndMethodInvocation(endLine: false);
}
internal override void VisitTagHelper(TagHelperIRNode node)
public override void VisitTagHelper(TagHelperIRNode node)
{
var initialTagHelperRenderingContext = Context.TagHelperRenderingContext;
Context.TagHelperRenderingContext = new TagHelperRenderingContext();
@ -209,12 +209,12 @@ namespace Microsoft.AspNetCore.Razor.Evolution
Context.TagHelperRenderingContext = initialTagHelperRenderingContext;
}
internal override void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
public override void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
{
VisitDefault(node);
}
internal override void VisitCreateTagHelper(CreateTagHelperIRNode node)
public override void VisitCreateTagHelper(CreateTagHelperIRNode node)
{
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
@ -226,7 +226,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
.WriteEndMethodInvocation();
}
internal override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
{
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
var tagHelperRenderingContext = Context.TagHelperRenderingContext;
@ -312,7 +312,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
}
}
internal override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
public override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
{
foreach (var tagHelperTypeName in node.UsedTagHelperTypeNames)
{

View File

@ -269,7 +269,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
Context.Writer.WriteEndMethodInvocation(endLine: false);
}
internal override void VisitTagHelper(TagHelperIRNode node)
public override void VisitTagHelper(TagHelperIRNode node)
{
var initialTagHelperRenderingContext = Context.TagHelperRenderingContext;
Context.TagHelperRenderingContext = new TagHelperRenderingContext();
@ -277,7 +277,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
Context.TagHelperRenderingContext = initialTagHelperRenderingContext;
}
internal override void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
public override void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
{
// Call into the tag helper scope manager to start a new tag helper scope.
// Also capture the value as the current execution context.
@ -311,7 +311,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
Context.Writer.WriteEndMethodInvocation();
}
internal override void VisitCreateTagHelper(CreateTagHelperIRNode node)
public override void VisitCreateTagHelper(CreateTagHelperIRNode node)
{
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
@ -328,7 +328,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
tagHelperVariableName);
}
internal override void VisitAddPreallocatedTagHelperHtmlAttribute(AddPreallocatedTagHelperHtmlAttributeIRNode node)
public override void VisitAddPreallocatedTagHelperHtmlAttribute(AddPreallocatedTagHelperHtmlAttributeIRNode node)
{
Context.Writer
.WriteStartInstanceMethodInvocation(
@ -338,7 +338,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
.WriteEndMethodInvocation();
}
internal override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
public override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
{
var attributeValueStyleParameter = $"global::{typeof(HtmlAttributeValueStyle).FullName}.{node.ValueStyle}";
var isConditionalAttributeValue = node.Children.Any(child => child is CSharpAttributeValueIRNode);
@ -409,7 +409,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
}
}
internal override void VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
public override void VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
{
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
var propertyValueAccessor = GetTagHelperPropertyAccessor(tagHelperVariableName, node.AttributeName, node.Descriptor);
@ -426,7 +426,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
.WriteEndMethodInvocation();
}
internal override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
{
var tagHelperVariableName = GetTagHelperVariableName(node.TagHelperTypeName);
var tagHelperRenderingContext = Context.TagHelperRenderingContext;
@ -528,7 +528,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
.WriteEndMethodInvocation();
}
internal override void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
public override void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
{
Context.Writer
.Write("await ")
@ -568,7 +568,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
"End" /* ORIGINAL: ScopeManagerEndMethodName */);
}
internal override void VisitDeclarePreallocatedTagHelperHtmlAttribute(DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
public override void VisitDeclarePreallocatedTagHelperHtmlAttribute(DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
{
Context.Writer
.Write("private static readonly global::")
@ -596,7 +596,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
}
}
internal override void VisitDeclarePreallocatedTagHelperAttribute(DeclarePreallocatedTagHelperAttributeIRNode node)
public override void VisitDeclarePreallocatedTagHelperAttribute(DeclarePreallocatedTagHelperAttributeIRNode node)
{
Context.Writer
.Write("private static readonly global::")
@ -613,7 +613,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
.WriteEndMethodInvocation();
}
internal override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
public override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
{
Context.Writer.WriteLineHiddenDirective();

View File

@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.AspNetCore.Razor.Evolution
{
public interface ITagHelperFeature : IRazorEngineFeature
{
ITagHelperDescriptorResolver Resolver { get; }
}
}

View File

@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
internal class AddPreallocatedTagHelperHtmlAttributeIRNode : RazorIRNode
public class AddPreallocatedTagHelperHtmlAttributeIRNode : RazorIRNode
{
public override IList<RazorIRNode> Children { get; } = EmptyArray;

View File

@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
internal class AddTagHelperHtmlAttributeIRNode : RazorIRNode
public class AddTagHelperHtmlAttributeIRNode : RazorIRNode
{
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();

View File

@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
internal class CreateTagHelperIRNode : RazorIRNode
public class CreateTagHelperIRNode : RazorIRNode
{
public override IList<RazorIRNode> Children { get; } = EmptyArray;
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
public string TagHelperTypeName { get; set; }
internal TagHelperDescriptor Descriptor { get; set; }
public TagHelperDescriptor Descriptor { get; set; }
public override void Accept(RazorIRNodeVisitor visitor)
{

View File

@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
internal class DeclarePreallocatedTagHelperAttributeIRNode : RazorIRNode
public class DeclarePreallocatedTagHelperAttributeIRNode : RazorIRNode
{
public override IList<RazorIRNode> Children { get; } = EmptyArray;

View File

@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
internal class DeclarePreallocatedTagHelperHtmlAttributeIRNode : RazorIRNode
public class DeclarePreallocatedTagHelperHtmlAttributeIRNode : RazorIRNode
{
public override IList<RazorIRNode> Children { get; } = EmptyArray;

View File

@ -3,11 +3,10 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
internal class DeclareTagHelperFieldsIRNode : RazorIRNode
public class DeclareTagHelperFieldsIRNode : RazorIRNode
{
public override IList<RazorIRNode> Children { get; } = EmptyArray;

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
internal class ExecuteTagHelpersIRNode : RazorIRNode
public class ExecuteTagHelpersIRNode : RazorIRNode
{
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();

View File

@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
internal class InitializeTagHelperStructureIRNode : RazorIRNode
public class InitializeTagHelperStructureIRNode : RazorIRNode
{
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();

View File

@ -94,57 +94,57 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
VisitDefault(node);
}
internal virtual void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
public virtual void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
{
VisitDefault(node);
}
internal virtual void VisitTagHelper(TagHelperIRNode node)
public virtual void VisitTagHelper(TagHelperIRNode node)
{
VisitDefault(node);
}
internal virtual void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
public virtual void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
{
VisitDefault(node);
}
internal virtual void VisitCreateTagHelper(CreateTagHelperIRNode node)
public virtual void VisitCreateTagHelper(CreateTagHelperIRNode node)
{
VisitDefault(node);
}
internal virtual void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
public virtual void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
{
VisitDefault(node);
}
internal virtual void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
public virtual void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
{
VisitDefault(node);
}
internal virtual void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
public virtual void VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
{
VisitDefault(node);
}
internal virtual void VisitDeclarePreallocatedTagHelperHtmlAttribute(DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
public virtual void VisitDeclarePreallocatedTagHelperHtmlAttribute(DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
{
VisitDefault(node);
}
internal virtual void VisitAddPreallocatedTagHelperHtmlAttribute(AddPreallocatedTagHelperHtmlAttributeIRNode node)
public virtual void VisitAddPreallocatedTagHelperHtmlAttribute(AddPreallocatedTagHelperHtmlAttributeIRNode node)
{
VisitDefault(node);
}
internal virtual void VisitDeclarePreallocatedTagHelperAttribute(DeclarePreallocatedTagHelperAttributeIRNode node)
public virtual void VisitDeclarePreallocatedTagHelperAttribute(DeclarePreallocatedTagHelperAttributeIRNode node)
{
VisitDefault(node);
}
internal virtual void VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
public virtual void VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
{
VisitDefault(node);
}

View File

@ -95,57 +95,57 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
return VisitDefault(node);
}
internal virtual TResult VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
public virtual TResult VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
{
return VisitDefault(node);
}
internal virtual TResult VisitTagHelper(TagHelperIRNode node)
public virtual TResult VisitTagHelper(TagHelperIRNode node)
{
return VisitDefault(node);
}
internal virtual TResult VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
public virtual TResult VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
{
return VisitDefault(node);
}
internal virtual TResult VisitCreateTagHelper(CreateTagHelperIRNode node)
public virtual TResult VisitCreateTagHelper(CreateTagHelperIRNode node)
{
return VisitDefault(node);
}
internal virtual TResult VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
public virtual TResult VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
{
return VisitDefault(node);
}
internal virtual TResult VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
public virtual TResult VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
{
return VisitDefault(node);
}
internal virtual TResult VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
public virtual TResult VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
{
return VisitDefault(node);
}
internal virtual TResult VisitDeclarePreallocatedTagHelperHtmlAttribute(DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
public virtual TResult VisitDeclarePreallocatedTagHelperHtmlAttribute(DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
{
return VisitDefault(node);
}
internal virtual TResult VisitAddPreallocatedTagHelperHtmlAttribute(AddPreallocatedTagHelperHtmlAttributeIRNode node)
public virtual TResult VisitAddPreallocatedTagHelperHtmlAttribute(AddPreallocatedTagHelperHtmlAttributeIRNode node)
{
return VisitDefault(node);
}
internal virtual TResult VisitDeclarePreallocatedTagHelperAttribute(DeclarePreallocatedTagHelperAttributeIRNode node)
public virtual TResult VisitDeclarePreallocatedTagHelperAttribute(DeclarePreallocatedTagHelperAttributeIRNode node)
{
return VisitDefault(node);
}
internal virtual TResult VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
public virtual TResult VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
{
return VisitDefault(node);
}

View File

@ -2,11 +2,10 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
internal class SetPreallocatedTagHelperPropertyIRNode : RazorIRNode
public class SetPreallocatedTagHelperPropertyIRNode : RazorIRNode
{
public override IList<RazorIRNode> Children { get; } = EmptyArray;

View File

@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
internal class SetTagHelperPropertyIRNode : RazorIRNode
public class SetTagHelperPropertyIRNode : RazorIRNode
{
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();

View File

@ -3,11 +3,10 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
internal class TagHelperIRNode : RazorIRNode
public class TagHelperIRNode : RazorIRNode
{
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();

View File

@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
/// <summary>
/// Used to manage <see cref="RazorError"/>s encountered during the Razor parsing phase.
/// </summary>
internal class ErrorSink
public class ErrorSink
{
private readonly List<RazorError> _errors;

View File

@ -3,7 +3,7 @@
namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
{
internal enum HtmlAttributeValueStyle
public enum HtmlAttributeValueStyle
{
DoubleQuotes,
SingleQuotes,

View File

@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
/// <summary>
/// Contract used to resolve <see cref="TagHelperDescriptor"/>s.
/// </summary>
internal interface ITagHelperDescriptorResolver
public interface ITagHelperDescriptorResolver
{
IEnumerable<TagHelperDescriptor> Resolve(ErrorSink errorSink);
}

View File

@ -7,7 +7,7 @@ using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Razor.Evolution.Legacy
{
internal class RazorError : IEquatable<RazorError>
public class RazorError : IEquatable<RazorError>
{
internal static readonly RazorError[] EmptyArray = new RazorError[0];

View File

@ -3,6 +3,8 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.Evolution.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Workspaces.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Workspaces, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Remote.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View File

@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
VisitDefault(node);
}
internal override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
public override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
{
if (node.Children.Count != 1 || !(node.Children.First() is HtmlContentIRNode))
{
@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
node.Parent.Children[nodeIndex] = addPreAllocatedAttribute;
}
internal override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
{
if (!node.Descriptor.IsStringProperty ||
node.Children.Count != 1 ||

View File

@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
public RazorSyntaxTree Execute(RazorCodeDocument codeDocument, RazorSyntaxTree syntaxTree)
{
var resolver = Engine.Features.OfType<TagHelperFeature>().FirstOrDefault()?.Resolver;
var resolver = Engine.Features.OfType<ITagHelperFeature>().FirstOrDefault()?.Resolver;
if (resolver == null)
{
// No resolver, nothing to do.

View File

@ -1,19 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.AspNetCore.Razor.Evolution
{
internal class TagHelperFeature : IRazorEngineFeature
{
public TagHelperFeature(ITagHelperDescriptorResolver resolver)
{
Resolver = resolver;
}
public RazorEngine Engine { get; set; }
public ITagHelperDescriptorResolver Resolver { get; }
}
}

View File

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
@ -11,18 +10,9 @@ namespace Microsoft.CodeAnalysis.Razor
{
internal class DefaultTagHelperResolver : TagHelperResolver
{
private static readonly Version SupportedVCTHMvcVersion = new Version(1, 1);
private readonly string ViewComponentAssembly;
public DefaultTagHelperResolver(bool designTime) : this(designTime, ViewComponentTypes.Assembly)
{
}
// Internal for testing
internal DefaultTagHelperResolver(bool designTime, string viewComponentAssembly)
public DefaultTagHelperResolver(bool designTime)
{
DesignTime = designTime;
ViewComponentAssembly = viewComponentAssembly;
}
public bool DesignTime { get; }
@ -40,15 +30,8 @@ namespace Microsoft.CodeAnalysis.Razor
private void VisitTagHelpers(Compilation compilation, List<TagHelperDescriptor> results, ErrorSink errors)
{
var @interface = compilation.GetTypeByMetadataName(TagHelperTypes.ITagHelper);
if (@interface == null)
{
// If ITagHelper isn't defined, then we couldn't possibly find anything.
return;
}
var types = new List<INamedTypeSymbol>();
var visitor = new TagHelperVisitor(@interface, types);
var visitor = TagHelperTypeVisitor.Create(compilation, types);
VisitCompilation(visitor, compilation);
@ -63,20 +46,8 @@ namespace Microsoft.CodeAnalysis.Razor
private void VisitViewComponents(Compilation compilation, List<TagHelperDescriptor> results, ErrorSink errors)
{
var mvcViewFeaturesAssembly = compilation.References
.Select(reference => compilation.GetAssemblyOrModuleSymbol(reference))
.OfType<IAssemblySymbol>()
.FirstOrDefault(assembly => string.Equals(assembly.Identity.Name, ViewComponentAssembly, StringComparison.Ordinal));
if (mvcViewFeaturesAssembly == null || mvcViewFeaturesAssembly.Identity.Version < SupportedVCTHMvcVersion)
{
return;
}
var viewComponentAttributeSymbol = compilation.GetTypeByMetadataName(ViewComponentTypes.ViewComponentAttribute);
var nonViewComponentAttributeSymbol = compilation.GetTypeByMetadataName(ViewComponentTypes.NonViewComponentAttribute);
var types = new List<INamedTypeSymbol>();
var visitor = new ViewComponentVisitor(viewComponentAttributeSymbol, viewComponentAttributeSymbol, types);
var visitor = ViewComponentTypeVisitor.Create(compilation, types);
VisitCompilation(visitor, compilation);
@ -109,116 +80,5 @@ namespace Microsoft.CodeAnalysis.Razor
}
}
}
// Visits top-level types and finds interface implementations.
internal class TagHelperVisitor : SymbolVisitor
{
private INamedTypeSymbol _interface;
private List<INamedTypeSymbol> _results;
public TagHelperVisitor(INamedTypeSymbol @interface, List<INamedTypeSymbol> results)
{
_interface = @interface;
_results = results;
}
public override void VisitNamedType(INamedTypeSymbol symbol)
{
if (IsTagHelper(symbol))
{
_results.Add(symbol);
}
}
public override void VisitNamespace(INamespaceSymbol symbol)
{
foreach (var member in symbol.GetMembers())
{
Visit(member);
}
}
internal bool IsTagHelper(INamedTypeSymbol symbol)
{
return symbol.DeclaredAccessibility == Accessibility.Public &&
!symbol.IsAbstract &&
!symbol.IsGenericType &&
symbol.AllInterfaces.Contains(_interface);
}
}
internal class ViewComponentVisitor : SymbolVisitor
{
private INamedTypeSymbol _viewComponentAttribute;
private INamedTypeSymbol _nonViewComponentAttribute;
private List<INamedTypeSymbol> _results;
public ViewComponentVisitor(
INamedTypeSymbol viewComponentAttribute,
INamedTypeSymbol nonViewComponentAttribute,
List<INamedTypeSymbol> 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 (symbol.DeclaredAccessibility != Accessibility.Public ||
symbol.IsAbstract ||
symbol.IsGenericType ||
AttributeIsDefined(symbol, _nonViewComponentAttribute))
{
return false;
}
return symbol.Name.EndsWith(ViewComponentTypes.ViewComponentSuffix) ||
AttributeIsDefined(symbol, _viewComponentAttribute);
}
private static bool AttributeIsDefined(INamedTypeSymbol type, INamedTypeSymbol queryAttribute)
{
if (type == null)
{
return false;
}
var attribute = type.GetAttributes().Where(a => a.AttributeClass == queryAttribute).FirstOrDefault();
if (attribute != null)
{
return true;
}
return AttributeIsDefined(type.BaseType, queryAttribute);
}
}
}
}

View File

@ -1,7 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<Import Project="..\..\build\common.props" />
<PropertyGroup>
<Description>Razor is a markup syntax for adding server-side logic to web pages. This package contains the Razor design-time infrastructure.</Description>
<TargetFrameworks>net451;netstandard1.3</TargetFrameworks>
@ -10,10 +8,9 @@
<PackageTags>aspnetcore;cshtml;razor</PackageTags>
<PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wp8+wpa81;</PackageTargetFallback>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="1.3.0" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Evolution\Microsoft.AspNetCore.Razor.Evolution.csproj" />
<ProjectReference Include="..\Microsoft.CodeAnalysis.Razor\Microsoft.CodeAnalysis.Razor.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Evolution;
namespace Microsoft.CodeAnalysis.Razor
{
public class DefaultMetadataReferenceFeature : IMetadataReferenceFeature
{
public RazorEngine Engine { get; set; }
public IReadOnlyList<MetadataReference> References { get; set; }
}
}

View File

@ -223,14 +223,14 @@ namespace Microsoft.CodeAnalysis.Razor
{
if (string.IsNullOrWhiteSpace(name))
{
var whitespaceError = Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidRestrictChildrenAttributeNameNullWhitespace(
var whitespaceError = Resources.FormatTagHelperDescriptorFactory_InvalidRestrictChildrenAttributeNameNullWhitespace(
TagHelperTypes.RestrictChildrenAttribute,
tagHelperName);
errorSink.OnError(SourceLocation.Zero, whitespaceError, length: 0);
}
else if (TryValidateName(
name,
invalidCharacter => Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidRestrictChildrenAttributeName(
invalidCharacter => Resources.FormatTagHelperDescriptorFactory_InvalidRestrictChildrenAttributeName(
TagHelperTypes.RestrictChildrenAttribute,
name,
tagHelperName,
@ -372,15 +372,15 @@ namespace Microsoft.CodeAnalysis.Razor
}
else if (string.IsNullOrWhiteSpace(parentTag))
{
var error = Workspaces.Resources.FormatHtmlTargetElementAttribute_NameCannotBeNullOrWhitespace(
Workspaces.Resources.TagHelperDescriptorFactory_ParentTag);
var error = Resources.FormatHtmlTargetElementAttribute_NameCannotBeNullOrWhitespace(
Resources.TagHelperDescriptorFactory_ParentTag);
errorSink.OnError(SourceLocation.Zero, error, length: 0);
return false;
}
else if (!TryValidateName(
parentTag,
invalidCharacter => Workspaces.Resources.FormatHtmlTargetElementAttribute_InvalidName(
Workspaces.Resources.TagHelperDescriptorFactory_ParentTag.ToLower(),
invalidCharacter => Resources.FormatHtmlTargetElementAttribute_InvalidName(
Resources.TagHelperDescriptorFactory_ParentTag.ToLower(),
parentTag,
invalidCharacter),
errorSink))
@ -414,18 +414,18 @@ namespace Microsoft.CodeAnalysis.Razor
}
var targetName = targetingAttributes ?
Workspaces.Resources.TagHelperDescriptorFactory_Attribute :
Workspaces.Resources.TagHelperDescriptorFactory_Tag;
Resources.TagHelperDescriptorFactory_Attribute :
Resources.TagHelperDescriptorFactory_Tag;
if (string.IsNullOrWhiteSpace(name))
{
var error = Workspaces.Resources.FormatHtmlTargetElementAttribute_NameCannotBeNullOrWhitespace(targetName);
var error = Resources.FormatHtmlTargetElementAttribute_NameCannotBeNullOrWhitespace(targetName);
errorSink.OnError(SourceLocation.Zero, error, length: 0);
return false;
}
else if (!TryValidateName(
name,
invalidCharacter => Workspaces.Resources.FormatHtmlTargetElementAttribute_InvalidName(
invalidCharacter => Resources.FormatHtmlTargetElementAttribute_InvalidName(
targetName.ToLower(),
name,
invalidCharacter),
@ -509,7 +509,7 @@ namespace Microsoft.CodeAnalysis.Razor
// Specified HtmlAttributeNameAttribute.Name though property has no public setter.
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameNotNullOrEmpty(
Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameNotNullOrEmpty(
GetFullName(type),
property.Name,
TagHelperTypes.HtmlAttributeNameAttribute,
@ -591,13 +591,13 @@ namespace Microsoft.CodeAnalysis.Razor
string nameOrPrefix;
if (attributeDescriptor.IsIndexer)
{
nameOrPrefix = Workspaces.Resources.TagHelperDescriptorFactory_Prefix;
nameOrPrefix = Resources.TagHelperDescriptorFactory_Prefix;
}
else if (string.IsNullOrEmpty(attributeDescriptor.Name))
{
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameNullOrEmpty(
Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameNullOrEmpty(
GetFullName(parentType),
attributeDescriptor.PropertyName),
length: 0);
@ -606,7 +606,7 @@ namespace Microsoft.CodeAnalysis.Razor
}
else
{
nameOrPrefix = Workspaces.Resources.TagHelperDescriptorFactory_Name;
nameOrPrefix = Resources.TagHelperDescriptorFactory_Name;
}
return ValidateTagHelperAttributeNameOrPrefix(
@ -639,7 +639,7 @@ namespace Microsoft.CodeAnalysis.Razor
// Provide a single error if the entire name is whitespace, not an error per character.
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameOrPrefixWhitespace(
Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameOrPrefixWhitespace(
GetFullName(parentType),
propertyName,
nameOrPrefix),
@ -654,7 +654,7 @@ namespace Microsoft.CodeAnalysis.Razor
{
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameOrPrefixStart(
Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameOrPrefixStart(
GetFullName(parentType),
propertyName,
nameOrPrefix,
@ -672,7 +672,7 @@ namespace Microsoft.CodeAnalysis.Razor
{
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameOrPrefixCharacter(
Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameOrPrefixCharacter(
GetFullName(parentType),
propertyName,
nameOrPrefix,
@ -749,7 +749,7 @@ namespace Microsoft.CodeAnalysis.Razor
isInvalid = true;
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributePrefixNotNull(
Resources.FormatTagHelperDescriptorFactory_InvalidAttributePrefixNotNull(
GetFullName(parentType),
property.Name,
TagHelperTypes.HtmlAttributeNameAttribute,
@ -764,7 +764,7 @@ namespace Microsoft.CodeAnalysis.Razor
isInvalid = true;
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameAttribute(
Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameAttribute(
GetFullName(parentType),
property.Name,
TagHelperTypes.HtmlAttributeNameAttribute,
@ -784,7 +784,7 @@ namespace Microsoft.CodeAnalysis.Razor
isInvalid = true;
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributePrefixNull(
Resources.FormatTagHelperDescriptorFactory_InvalidAttributePrefixNull(
GetFullName(parentType),
property.Name,
TagHelperTypes.HtmlAttributeNameAttribute,
@ -973,7 +973,7 @@ namespace Microsoft.CodeAnalysis.Razor
{
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeCharacter(Current, _requiredAttributes),
Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeCharacter(Current, _requiredAttributes),
length: 0);
return false;
}
@ -1055,7 +1055,7 @@ namespace Microsoft.CodeAnalysis.Razor
{
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_PartialRequiredAttributeOperator(_requiredAttributes, op),
Resources.FormatTagHelperDescriptorFactory_PartialRequiredAttributeOperator(_requiredAttributes, op),
length: 0);
return null;
}
@ -1064,7 +1064,7 @@ namespace Microsoft.CodeAnalysis.Razor
{
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeOperator(Current, _requiredAttributes),
Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeOperator(Current, _requiredAttributes),
length: 0);
return null;
}
@ -1089,7 +1089,7 @@ namespace Microsoft.CodeAnalysis.Razor
{
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeMismatchedQuotes(_requiredAttributes, quote),
Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeMismatchedQuotes(_requiredAttributes, quote),
length: 0);
return null;
}
@ -1164,7 +1164,7 @@ namespace Microsoft.CodeAnalysis.Razor
{
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_CouldNotFindMatchingEndBrace(_requiredAttributes),
Resources.FormatTagHelperDescriptorFactory_CouldNotFindMatchingEndBrace(_requiredAttributes),
length: 0);
return null;
}
@ -1172,7 +1172,7 @@ namespace Microsoft.CodeAnalysis.Razor
{
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeCharacter(Current, _requiredAttributes),
Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeCharacter(Current, _requiredAttributes),
length: 0);
return null;
}
@ -1192,7 +1192,7 @@ namespace Microsoft.CodeAnalysis.Razor
{
errorSink.OnError(
SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_CouldNotFindMatchingEndBrace(_requiredAttributes),
Resources.FormatTagHelperDescriptorFactory_CouldNotFindMatchingEndBrace(_requiredAttributes),
length: 0);
return false;

View File

@ -0,0 +1,53 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
using Microsoft.CodeAnalysis.CSharp;
namespace Microsoft.CodeAnalysis.Razor
{
public class DefaultTagHelperFeature : ITagHelperFeature
{
private RazorEngine _engine;
private IMetadataReferenceFeature _referenceFeature;
public RazorEngine Engine
{
get
{
return _engine;
}
set
{
_engine = value;
OnInitialized();
}
}
public ITagHelperDescriptorResolver Resolver { get; private set; }
private void OnInitialized()
{
_referenceFeature = Engine.Features.OfType<IMetadataReferenceFeature>().FirstOrDefault();
Resolver = new InnerResolver(_referenceFeature);
}
private class InnerResolver : ITagHelperDescriptorResolver
{
private readonly IMetadataReferenceFeature _referenceFeature;
public InnerResolver(IMetadataReferenceFeature referenceFeature)
{
_referenceFeature = referenceFeature;
}
public IEnumerable<TagHelperDescriptor> Resolve(ErrorSink errorSink)
{
var compilation = CSharpCompilation.Create("__TagHelpers", references: _referenceFeature.References);
return TagHelpers.GetTagHelpers(compilation);
}
}
}
}

View File

@ -0,0 +1,13 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Razor.Evolution;
using System.Collections.Generic;
namespace Microsoft.CodeAnalysis.Razor
{
public interface IMetadataReferenceFeature : IRazorEngineFeature
{
IReadOnlyList<MetadataReference> References { get; }
}
}

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<Import Project="..\..\build\common.props" />
<PropertyGroup>
<Description>Razor is a markup syntax for adding server-side logic to web pages. This package contains the Razor design-time infrastructure.</Description>
@ -10,6 +10,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="1.3.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="1.3.0" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Evolution\Microsoft.AspNetCore.Razor.Evolution.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Workspaces, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Workspaces.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Remote.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LanguageServices.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.RazorExtension, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]

View File

@ -1,5 +1,5 @@
// <auto-generated />
namespace Microsoft.CodeAnalysis.Razor.Workspaces
namespace Microsoft.CodeAnalysis.Razor
{
using System.Globalization;
using System.Reflection;
@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces
internal static class Resources
{
private static readonly ResourceManager _resourceManager
= new ResourceManager("Microsoft.CodeAnalysis.Razor.Workspaces.Resources", typeof(Resources).GetTypeInfo().Assembly);
= new ResourceManager("Microsoft.CodeAnalysis.Razor.Resources", typeof(Resources).GetTypeInfo().Assembly);
/// <summary>
/// {0} cannot be null or an empty string.

View File

@ -1,5 +1,5 @@
// <auto-generated />
namespace Microsoft.CodeAnalysis.Razor.Workspaces
namespace Microsoft.CodeAnalysis.Razor
{
using System.Globalization;
using System.Reflection;
@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces
internal static class ViewComponentResources
{
private static readonly ResourceManager _resourceManager
= new ResourceManager("Microsoft.CodeAnalysis.Razor.Workspaces.ViewComponentResources", typeof(ViewComponentResources).GetTypeInfo().Assembly);
= new ResourceManager("Microsoft.CodeAnalysis.Razor.ViewComponentResources", typeof(ViewComponentResources).GetTypeInfo().Assembly);
/// <summary>
/// View component '{0}' must have exactly one public method named '{1}' or '{2}'.

View File

@ -0,0 +1,56 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace Microsoft.CodeAnalysis.Razor
{
// Visits top-level types and finds interface implementations.
internal class TagHelperTypeVisitor : SymbolVisitor
{
private INamedTypeSymbol _interface;
private List<INamedTypeSymbol> _results;
public static TagHelperTypeVisitor Create(Compilation compilation, List<INamedTypeSymbol> results)
{
var @interface = compilation.GetTypeByMetadataName(TagHelperTypes.ITagHelper);
return new TagHelperTypeVisitor(@interface, results);
}
public TagHelperTypeVisitor(INamedTypeSymbol @interface, List<INamedTypeSymbol> results)
{
_interface = @interface;
_results = results;
}
public override void VisitNamedType(INamedTypeSymbol symbol)
{
if (IsTagHelper(symbol))
{
_results.Add(symbol);
}
}
public override void VisitNamespace(INamespaceSymbol symbol)
{
foreach (var member in symbol.GetMembers())
{
Visit(member);
}
}
internal bool IsTagHelper(INamedTypeSymbol symbol)
{
if (_interface == null)
{
return false;
}
return
symbol.DeclaredAccessibility == Accessibility.Public &&
!symbol.IsAbstract &&
!symbol.IsGenericType &&
symbol.AllInterfaces.Contains(_interface);
}
}
}

View File

@ -0,0 +1,77 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
using System;
using System.Collections.Generic;
namespace Microsoft.CodeAnalysis.Razor
{
public static class TagHelpers
{
public static IReadOnlyList<TagHelperDescriptor> GetTagHelpers(Compilation compilation)
{
var results = new List<TagHelperDescriptor>();
var errors = new ErrorSink();
VisitTagHelpers(compilation, results, errors);
VisitViewComponents(compilation, results, errors);
return results;
}
private static void VisitTagHelpers(Compilation compilation, List<TagHelperDescriptor> results, ErrorSink errors)
{
var types = new List<INamedTypeSymbol>();
var visitor = TagHelperTypeVisitor.Create(compilation, types);
VisitCompilation(visitor, compilation);
var factory = new DefaultTagHelperDescriptorFactory(compilation, designTime: false);
foreach (var type in types)
{
var descriptors = factory.CreateDescriptors(type, errors);
results.AddRange(descriptors);
}
}
private static void VisitViewComponents(Compilation compilation, List<TagHelperDescriptor> results, ErrorSink errors)
{
var types = new List<INamedTypeSymbol>();
var visitor = ViewComponentTypeVisitor.Create(compilation, types);
VisitCompilation(visitor, compilation);
var factory = new ViewComponentTagHelperDescriptorFactory(compilation);
foreach (var type in types)
{
try
{
var descriptor = factory.CreateDescriptor(type);
results.Add(descriptor);
}
catch (Exception ex)
{
errors.OnError(SourceLocation.Zero, ex.Message, length: 0);
}
}
}
private static void VisitCompilation(SymbolVisitor visitor, Compilation compilation)
{
visitor.Visit(compilation.Assembly.GlobalNamespace);
foreach (var reference in compilation.References)
{
if (compilation.GetAssemblyOrModuleSymbol(reference) is IAssemblySymbol assembly)
{
visitor.Visit(assembly.GlobalNamespace);
}
}
}
}
}

View File

@ -7,7 +7,6 @@ using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.CodeAnalysis.Razor.Workspaces;
namespace Microsoft.CodeAnalysis.Razor
{

View File

@ -0,0 +1,112 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.CodeAnalysis.Razor
{
internal class ViewComponentTypeVisitor : SymbolVisitor
{
private static readonly Version SupportedVCTHMvcVersion = new Version(1, 1);
private INamedTypeSymbol _viewComponentAttribute;
private INamedTypeSymbol _nonViewComponentAttribute;
private List<INamedTypeSymbol> _results;
public static ViewComponentTypeVisitor Create(Compilation compilation, List<INamedTypeSymbol> results)
{
var enabled = false;
foreach (var reference in compilation.References)
{
var symbol = compilation.GetAssemblyOrModuleSymbol(reference) as IAssemblySymbol;
if (symbol != null)
{
if (string.Equals(symbol.Identity.Name, ViewComponentTypes.Assembly, StringComparison.Ordinal) &&
symbol.Identity.Version > ViewComponentTypes.AssemblyVersion)
{
enabled = true;
break;
}
}
}
var vcAttribute = enabled ? compilation.GetTypeByMetadataName(ViewComponentTypes.ViewComponentAttribute) : null;
var nonVCAttribute = enabled ? compilation.GetTypeByMetadataName(ViewComponentTypes.NonViewComponentAttribute) : null;
return new ViewComponentTypeVisitor(vcAttribute, nonVCAttribute, results);
}
public ViewComponentTypeVisitor(
INamedTypeSymbol viewComponentAttribute,
INamedTypeSymbol nonViewComponentAttribute,
List<INamedTypeSymbol> 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) ||
AttributeIsDefined(symbol, _viewComponentAttribute);
}
private static bool AttributeIsDefined(INamedTypeSymbol type, INamedTypeSymbol queryAttribute)
{
if (type == null)
{
return false;
}
var attribute = type.GetAttributes().Where(a => a.AttributeClass == queryAttribute).FirstOrDefault();
if (attribute != null)
{
return true;
}
return AttributeIsDefined(type.BaseType, queryAttribute);
}
}
}

View File

@ -1,12 +1,16 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.CodeAnalysis.Razor
{
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";

View File

@ -5,7 +5,6 @@ using System;
using System.Diagnostics;
using System.Text;
using System.Xml.Linq;
using Microsoft.CodeAnalysis.Razor.Workspaces;
namespace Microsoft.CodeAnalysis.Razor
{

View File

@ -1421,7 +1421,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
builder =>
{
builder.Features.Add(new ApiSetsIRTestAdapter());
builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors)));
builder.AddTagHelpers(descriptors);
});
var document = CreateCodeDocument();
@ -1439,7 +1439,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
builder =>
{
builder.Features.Add(new ApiSetsIRTestAdapter());
builder.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(descriptors)));
builder.AddTagHelpers(descriptors);
});
var document = CreateCodeDocument();

View File

@ -87,47 +87,47 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
WriteContentNode(node, node.Content);
}
internal override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
public override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
{
WriteContentNode(node, node.UsedTagHelperTypeNames.ToArray());
}
internal override void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
public override void VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
{
WriteContentNode(node, node.TagName, string.Format("{0}.{1}", nameof(TagMode), node.TagMode));
}
internal override void VisitCreateTagHelper(CreateTagHelperIRNode node)
public override void VisitCreateTagHelper(CreateTagHelperIRNode node)
{
WriteContentNode(node, node.TagHelperTypeName);
}
internal override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
public override void VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
{
WriteContentNode(node, node.AttributeName, node.PropertyName, string.Format("HtmlAttributeValueStyle.{0}", node.ValueStyle));
}
internal override void VisitDeclarePreallocatedTagHelperAttribute(DeclarePreallocatedTagHelperAttributeIRNode node)
public override void VisitDeclarePreallocatedTagHelperAttribute(DeclarePreallocatedTagHelperAttributeIRNode node)
{
WriteContentNode(node, node.VariableName, node.Name, node.Value, string.Format("HtmlAttributeValueStyle.{0}", node.ValueStyle));
}
internal override void VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
public override void VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
{
WriteContentNode(node, node.VariableName, node.AttributeName, node.PropertyName);
}
internal override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
public override void VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
{
WriteContentNode(node, node.Name, string.Format("{0}.{1}", nameof(HtmlAttributeValueStyle), node.ValueStyle));
}
internal override void VisitDeclarePreallocatedTagHelperHtmlAttribute(DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
public override void VisitDeclarePreallocatedTagHelperHtmlAttribute(DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
{
WriteContentNode(node, node.VariableName, node.Name, node.Value, string.Format("{0}.{1}", nameof(HtmlAttributeValueStyle), node.ValueStyle));
}
internal override void VisitAddPreallocatedTagHelperHtmlAttribute(AddPreallocatedTagHelperHtmlAttributeIRNode node)
public override void VisitAddPreallocatedTagHelperHtmlAttribute(AddPreallocatedTagHelperHtmlAttributeIRNode node)
{
WriteContentNode(node, node.VariableName);
}

View File

@ -337,7 +337,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
builder?.Invoke(b);
b.Features.Add(new TagHelperFeature(new TestTagHelperDescriptorResolver(tagHelpers)));
b.AddTagHelpers(tagHelpers);
});
for (var i = 0; i < engine.Phases.Count; i++)

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.AspNetCore.Razor.Evolution
@ -9,14 +10,19 @@ namespace Microsoft.AspNetCore.Razor.Evolution
{
public static IRazorEngineBuilder AddTagHelpers(this IRazorEngineBuilder builder, params TagHelperDescriptor[] tagHelpers)
{
var resolver = (TestTagHelperDescriptorResolver)builder.Features.OfType<TagHelperFeature>().FirstOrDefault()?.Resolver;
if (resolver == null)
return AddTagHelpers(builder, (IEnumerable<TagHelperDescriptor>)tagHelpers);
}
public static IRazorEngineBuilder AddTagHelpers(this IRazorEngineBuilder builder, IEnumerable<TagHelperDescriptor> tagHelpers)
{
var feature = (TestTagHelperFeature)builder.Features.OfType<ITagHelperFeature>().FirstOrDefault();
if (feature == null)
{
resolver = new TestTagHelperDescriptorResolver();
builder.Features.Add(new TagHelperFeature(resolver));
feature = new TestTagHelperFeature();
builder.Features.Add(feature);
}
resolver.TagHelpers.AddRange(tagHelpers);
feature.TagHelpers.AddRange(tagHelpers);
return builder;
}
}

View File

@ -6,6 +6,7 @@ using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
using Xunit;
using System.Linq;
using Moq;
namespace Microsoft.AspNetCore.Razor.Evolution
{
@ -81,9 +82,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
// Arrange
var engine = RazorEngine.Create(builder =>
{
var tagHelperFeature = new TagHelperFeature(resolver: null);
builder.Features.Add(tagHelperFeature);
builder.Features.Add(Mock.Of<ITagHelperFeature>());
});
var pass = new TagHelperBinderSyntaxTreePass()
{
@ -107,9 +106,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
// Arrange
var engine = RazorEngine.Create(builder =>
{
var resolver = new TestTagHelperDescriptorResolver();
var tagHelperFeature = new TagHelperFeature(resolver);
builder.Features.Add(tagHelperFeature);
builder.Features.Add(new TestTagHelperFeature());
});
var pass = new TagHelperBinderSyntaxTreePass()
@ -136,9 +133,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
// Arrange
var engine = RazorEngine.Create(builder =>
{
var resolver = new TestTagHelperDescriptorResolver();
var tagHelperFeature = new TagHelperFeature(resolver);
builder.Features.Add(tagHelperFeature);
builder.Features.Add(new TestTagHelperFeature());
});
var pass = new TagHelperBinderSyntaxTreePass()
@ -173,8 +168,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
var engine = RazorEngine.Create(builder =>
{
var resolver = new ErrorLoggingTagHelperDescriptorResolver(resolverError);
var tagHelperFeature = new TagHelperFeature(resolver);
builder.Features.Add(tagHelperFeature);
builder.Features.Add(Mock.Of<ITagHelperFeature>(f => f.Resolver == resolver));
});
var pass = new TagHelperBinderSyntaxTreePass()

View File

@ -0,0 +1,27 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Razor.Evolution
{
public class TestTagHelperFeature : ITagHelperFeature
{
public TestTagHelperFeature()
{
Resolver = new TestTagHelperDescriptorResolver();
}
public TestTagHelperFeature(IEnumerable<TagHelperDescriptor> tagHelpers)
{
Resolver = new TestTagHelperDescriptorResolver(tagHelpers);
}
public RazorEngine Engine { get; set; }
public List<TagHelperDescriptor> TagHelpers => ((TestTagHelperDescriptorResolver)Resolver).TagHelpers;
public ITagHelperDescriptorResolver Resolver { get; }
}
}

View File

@ -0,0 +1,121 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.CodeAnalysis.Razor.Workspaces.Test;
using Xunit;
namespace Microsoft.CodeAnalysis.Razor.Workspaces
{
public class TagHelperTypeVisitorTest
{
private static Compilation Compilation { get; } = TestCompilation.Create();
private static INamedTypeSymbol ITagHelperSymbol { get; } = Compilation.GetTypeByMetadataName(TagHelperTypes.ITagHelper);
[Fact]
public void IsTagHelper_PlainTagHelper_ReturnsTrue()
{
// Arrange
var testVisitor = new TagHelperTypeVisitor(ITagHelperSymbol, new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Valid_PlainTagHelper).FullName);
// Act
var isTagHelper = testVisitor.IsTagHelper(tagHelperSymbol);
// Assert
Assert.True(isTagHelper);
}
[Fact]
public void IsTagHelper_InheritedTagHelper_ReturnsTrue()
{
// Arrange
var testVisitor = new TagHelperTypeVisitor(ITagHelperSymbol, new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Valid_InheritedTagHelper).FullName);
// Act
var isTagHelper = testVisitor.IsTagHelper(tagHelperSymbol);
// Assert
Assert.True(isTagHelper);
}
[Fact]
public void IsTagHelper_AbstractTagHelper_ReturnsFalse()
{
// Arrange
var testVisitor = new TagHelperTypeVisitor(ITagHelperSymbol, new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_AbstractTagHelper).FullName);
// Act
var isTagHelper = testVisitor.IsTagHelper(tagHelperSymbol);
// Assert
Assert.False(isTagHelper);
}
[Fact]
public void IsTagHelper_GenericTagHelper_ReturnsFalse()
{
// Arrange
var testVisitor = new TagHelperTypeVisitor(ITagHelperSymbol, new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_GenericTagHelper<>).FullName);
// Act
var isTagHelper = testVisitor.IsTagHelper(tagHelperSymbol);
// Assert
Assert.False(isTagHelper);
}
[Fact]
public void IsTagHelper_InternalTagHelper_ReturnsFalse()
{
// Arrange
var testVisitor = new TagHelperTypeVisitor(ITagHelperSymbol, new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_InternalTagHelper).FullName);
// Act
var isTagHelper = testVisitor.IsTagHelper(tagHelperSymbol);
// Assert
Assert.False(isTagHelper);
}
public class Invalid_NestedPublicTagHelper : TagHelper
{
}
public class Valid_NestedPublicViewComponent
{
public string Invoke(string foo) => null;
}
}
public abstract class Invalid_AbstractTagHelper : TagHelper
{
}
public class Invalid_GenericTagHelper<T> : TagHelper
{
}
internal class Invalid_InternalTagHelper : TagHelper
{
}
public class Valid_PlainTagHelper : TagHelper
{
}
public class Valid_InheritedTagHelper : Valid_PlainTagHelper
{
}
}

View File

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
namespace Microsoft.CodeAnalysis.Razor.Workspaces.Test
namespace Microsoft.CodeAnalysis.Razor
{
public static class TestCompilation
{

View File

@ -0,0 +1,198 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Xunit;
namespace Microsoft.CodeAnalysis.Razor
{
public class ViewComponentTypeVisitorTest
{
private static Compilation Compilation { get; } = TestCompilation.Create();
// In practice MVC will provide a marker attribute for ViewComponents. To prevent a circular reference between MVC and Razor
// we can use a test class as a marker.
private static INamedTypeSymbol TestViewComponentAttributeSymbol { get; } = Compilation.GetTypeByMetadataName(typeof(TestViewComponentAttribute).FullName);
private static INamedTypeSymbol TestNonViewComponentAttributeSymbol { get; } = Compilation.GetTypeByMetadataName(typeof(TestNonViewComponentAttribute).FullName);
[Fact]
public void IsViewComponent_PlainViewComponent_ReturnsTrue()
{
// Arrange
var testVisitor = new ViewComponentTypeVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Valid_PlainViewComponent).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.True(isViewComponent);
}
[Fact]
public void IsViewComponent_DecoratedViewComponent_ReturnsTrue()
{
// Arrange
var testVisitor = new ViewComponentTypeVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Valid_DecoratedVC).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.True(isViewComponent);
}
[Fact]
public void IsViewComponent_InheritedViewComponent_ReturnsTrue()
{
// Arrange
var testVisitor = new ViewComponentTypeVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Valid_InheritedVC).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.True(isViewComponent);
}
[Fact]
public void IsViewComponent_AbstractViewComponent_ReturnsFalse()
{
// Arrange
var testVisitor = new ViewComponentTypeVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_AbstractViewComponent).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.False(isViewComponent);
}
[Fact]
public void IsViewComponent_GenericViewComponent_ReturnsFalse()
{
// Arrange
var testVisitor = new ViewComponentTypeVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_GenericViewComponent<>).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.False(isViewComponent);
}
[Fact]
public void IsViewComponent_InternalViewComponent_ReturnsFalse()
{
// Arrange
var testVisitor = new ViewComponentTypeVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_InternalViewComponent).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.False(isViewComponent);
}
[Fact]
public void IsViewComponent_DecoratedNonViewComponent_ReturnsFalse()
{
// Arrange
var testVisitor = new ViewComponentTypeVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_DecoratedViewComponent).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.False(isViewComponent);
}
[Fact]
public void IsViewComponent_InheritedNonViewComponent_ReturnsFalse()
{
// Arrange
var testVisitor = new ViewComponentTypeVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_InheritedViewComponent).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.False(isViewComponent);
}
public abstract class Invalid_AbstractViewComponent
{
}
public class Invalid_GenericViewComponent<T>
{
}
internal class Invalid_InternalViewComponent
{
}
public class Valid_PlainViewComponent
{
}
[TestViewComponent]
public class Valid_DecoratedVC
{
}
public class Valid_InheritedVC : Valid_DecoratedVC
{
}
[TestNonViewComponent]
public class Invalid_DecoratedViewComponent
{
}
[TestViewComponent]
public class Invalid_InheritedViewComponent : Invalid_DecoratedViewComponent
{
}
public class TestViewComponentAttribute : Attribute
{
}
public class TestNonViewComponentAttribute : Attribute
{
}
}
}

View File

@ -1,334 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.CodeAnalysis.Razor.Workspaces.Test;
using Xunit;
namespace Microsoft.CodeAnalysis.Razor.Workspaces
{
public class DefaultTagHelperResolverTest
{
private static Compilation Compilation { get; } = TestCompilation.Create();
private static INamedTypeSymbol ITagHelperSymbol { get; } = Compilation.GetTypeByMetadataName(TagHelperTypes.ITagHelper);
// In practice MVC will provide a marker attribute for ViewComponents. To prevent a circular reference between MVC and Razor
// we can use a test class as a marker.
private static INamedTypeSymbol TestViewComponentAttributeSymbol { get; } = Compilation.GetTypeByMetadataName(typeof(TestViewComponentAttribute).FullName);
private static INamedTypeSymbol TestNonViewComponentAttributeSymbol { get; } = Compilation.GetTypeByMetadataName(typeof(TestNonViewComponentAttribute).FullName);
[Fact]
public void IsTagHelper_PlainTagHelper_ReturnsTrue()
{
// Arrange
var testVisitor = new DefaultTagHelperResolver.TagHelperVisitor(ITagHelperSymbol, new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Valid_PlainTagHelper).FullName);
// Act
var isTagHelper = testVisitor.IsTagHelper(tagHelperSymbol);
// Assert
Assert.True(isTagHelper);
}
[Fact]
public void IsTagHelper_InheritedTagHelper_ReturnsTrue()
{
// Arrange
var testVisitor = new DefaultTagHelperResolver.TagHelperVisitor(ITagHelperSymbol, new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Valid_InheritedTagHelper).FullName);
// Act
var isTagHelper = testVisitor.IsTagHelper(tagHelperSymbol);
// Assert
Assert.True(isTagHelper);
}
[Fact]
public void IsTagHelper_AbstractTagHelper_ReturnsFalse()
{
// Arrange
var testVisitor = new DefaultTagHelperResolver.TagHelperVisitor(ITagHelperSymbol, new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_AbstractTagHelper).FullName);
// Act
var isTagHelper = testVisitor.IsTagHelper(tagHelperSymbol);
// Assert
Assert.False(isTagHelper);
}
[Fact]
public void IsTagHelper_GenericTagHelper_ReturnsFalse()
{
// Arrange
var testVisitor = new DefaultTagHelperResolver.TagHelperVisitor(ITagHelperSymbol, new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_GenericTagHelper<>).FullName);
// Act
var isTagHelper = testVisitor.IsTagHelper(tagHelperSymbol);
// Assert
Assert.False(isTagHelper);
}
[Fact]
public void IsTagHelper_InternalTagHelper_ReturnsFalse()
{
// Arrange
var testVisitor = new DefaultTagHelperResolver.TagHelperVisitor(ITagHelperSymbol, new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_InternalTagHelper).FullName);
// Act
var isTagHelper = testVisitor.IsTagHelper(tagHelperSymbol);
// Assert
Assert.False(isTagHelper);
}
[Fact]
public void GetTagHelpers_NestedTagHelpersAreNotFound()
{
// Arrange
var resolver = new DefaultTagHelperResolver(designTime: false);
var expectedTypeName = typeof(DefaultTagHelperResolver).FullName + "." + nameof(Invalid_NestedPublicTagHelper);
// Act
var descriptors = resolver.GetTagHelpers(Compilation);
// Assert
var matchingDescriptors = descriptors
.Where(descriptor => string.Equals(descriptor.TypeName, expectedTypeName, StringComparison.Ordinal));
Assert.Empty(matchingDescriptors);
}
[Fact]
public void IsViewComponent_PlainViewComponent_ReturnsTrue()
{
// Arrange
var testVisitor = new DefaultTagHelperResolver.ViewComponentVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Valid_PlainViewComponent).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.True(isViewComponent);
}
[Fact]
public void IsViewComponent_DecoratedViewComponent_ReturnsTrue()
{
// Arrange
var testVisitor = new DefaultTagHelperResolver.ViewComponentVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Valid_DecoratedVC).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.True(isViewComponent);
}
[Fact]
public void IsViewComponent_InheritedViewComponent_ReturnsTrue()
{
// Arrange
var testVisitor = new DefaultTagHelperResolver.ViewComponentVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Valid_InheritedVC).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.True(isViewComponent);
}
[Fact]
public void IsViewComponent_AbstractViewComponent_ReturnsFalse()
{
// Arrange
var testVisitor = new DefaultTagHelperResolver.ViewComponentVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_AbstractViewComponent).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.False(isViewComponent);
}
[Fact]
public void IsViewComponent_GenericViewComponent_ReturnsFalse()
{
// Arrange
var testVisitor = new DefaultTagHelperResolver.ViewComponentVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_GenericViewComponent<>).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.False(isViewComponent);
}
[Fact]
public void IsViewComponent_InternalViewComponent_ReturnsFalse()
{
// Arrange
var testVisitor = new DefaultTagHelperResolver.ViewComponentVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_InternalViewComponent).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.False(isViewComponent);
}
[Fact]
public void GetTagHelpers_NestedViewComponentTagHelpersAreFound()
{
// Arrange
var resolver = new DefaultTagHelperResolver(
designTime: false,
viewComponentAssembly: typeof(DefaultTagHelperResolverTest).Assembly.GetName().Name);
var expectedTypeName = "__Generated__" + nameof(Valid_NestedPublicViewComponent) + "TagHelper";
// Act
var descriptors = resolver.GetTagHelpers(Compilation);
// Assert
Assert.Single(descriptors, descriptor => string.Equals(descriptor.TypeName, expectedTypeName, StringComparison.Ordinal));
}
[Fact]
public void IsViewComponent_DecoratedNonViewComponent_ReturnsFalse()
{
// Arrange
var testVisitor = new DefaultTagHelperResolver.ViewComponentVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_DecoratedViewComponent).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.False(isViewComponent);
}
[Fact]
public void IsViewComponent_InheritedNonViewComponent_ReturnsFalse()
{
// Arrange
var testVisitor = new DefaultTagHelperResolver.ViewComponentVisitor(
TestViewComponentAttributeSymbol,
TestNonViewComponentAttributeSymbol,
new List<INamedTypeSymbol>());
var tagHelperSymbol = Compilation.GetTypeByMetadataName(typeof(Invalid_InheritedViewComponent).FullName);
// Act
var isViewComponent = testVisitor.IsViewComponent(tagHelperSymbol);
// Assert
Assert.False(isViewComponent);
}
public class Invalid_NestedPublicTagHelper : TagHelper
{
}
public class Valid_NestedPublicViewComponent
{
public string Invoke(string foo) => null;
}
}
public abstract class Invalid_AbstractTagHelper : TagHelper
{
}
public class Invalid_GenericTagHelper<T> : TagHelper
{
}
internal class Invalid_InternalTagHelper : TagHelper
{
}
public class Valid_PlainTagHelper : TagHelper
{
}
public class Valid_InheritedTagHelper : Valid_PlainTagHelper
{
}
public abstract class Invalid_AbstractViewComponent
{
}
public class Invalid_GenericViewComponent<T>
{
}
internal class Invalid_InternalViewComponent
{
}
public class Valid_PlainViewComponent
{
}
[TestViewComponent]
public class Valid_DecoratedVC
{
}
public class Valid_InheritedVC : Valid_DecoratedVC
{
}
[TestNonViewComponent]
public class Invalid_DecoratedViewComponent
{
}
[TestViewComponent]
public class Invalid_InheritedViewComponent : Invalid_DecoratedViewComponent
{
}
public class TestViewComponentAttribute : Attribute
{
}
public class TestNonViewComponentAttribute : Attribute
{
}
}