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); _namespace.AddAfter<UsingStatementIRNode>(node);
} }
internal override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node) public override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
{ {
_class.Insert(0, node); _class.Insert(0, node);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -95,57 +95,57 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
return VisitDefault(node); return VisitDefault(node);
} }
internal virtual TResult VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node) public virtual TResult VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
{ {
return VisitDefault(node); return VisitDefault(node);
} }
internal virtual TResult VisitTagHelper(TagHelperIRNode node) public virtual TResult VisitTagHelper(TagHelperIRNode node)
{ {
return VisitDefault(node); return VisitDefault(node);
} }
internal virtual TResult VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node) public virtual TResult VisitInitializeTagHelperStructure(InitializeTagHelperStructureIRNode node)
{ {
return VisitDefault(node); return VisitDefault(node);
} }
internal virtual TResult VisitCreateTagHelper(CreateTagHelperIRNode node) public virtual TResult VisitCreateTagHelper(CreateTagHelperIRNode node)
{ {
return VisitDefault(node); return VisitDefault(node);
} }
internal virtual TResult VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node) public virtual TResult VisitSetTagHelperProperty(SetTagHelperPropertyIRNode node)
{ {
return VisitDefault(node); return VisitDefault(node);
} }
internal virtual TResult VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node) public virtual TResult VisitAddTagHelperHtmlAttribute(AddTagHelperHtmlAttributeIRNode node)
{ {
return VisitDefault(node); return VisitDefault(node);
} }
internal virtual TResult VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node) public virtual TResult VisitExecuteTagHelpers(ExecuteTagHelpersIRNode node)
{ {
return VisitDefault(node); return VisitDefault(node);
} }
internal virtual TResult VisitDeclarePreallocatedTagHelperHtmlAttribute(DeclarePreallocatedTagHelperHtmlAttributeIRNode node) public virtual TResult VisitDeclarePreallocatedTagHelperHtmlAttribute(DeclarePreallocatedTagHelperHtmlAttributeIRNode node)
{ {
return VisitDefault(node); return VisitDefault(node);
} }
internal virtual TResult VisitAddPreallocatedTagHelperHtmlAttribute(AddPreallocatedTagHelperHtmlAttributeIRNode node) public virtual TResult VisitAddPreallocatedTagHelperHtmlAttribute(AddPreallocatedTagHelperHtmlAttributeIRNode node)
{ {
return VisitDefault(node); return VisitDefault(node);
} }
internal virtual TResult VisitDeclarePreallocatedTagHelperAttribute(DeclarePreallocatedTagHelperAttributeIRNode node) public virtual TResult VisitDeclarePreallocatedTagHelperAttribute(DeclarePreallocatedTagHelperAttributeIRNode node)
{ {
return VisitDefault(node); return VisitDefault(node);
} }
internal virtual TResult VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node) public virtual TResult VisitSetPreallocatedTagHelperProperty(SetPreallocatedTagHelperPropertyIRNode node)
{ {
return VisitDefault(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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;
namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{ {
internal class SetPreallocatedTagHelperPropertyIRNode : RazorIRNode public class SetPreallocatedTagHelperPropertyIRNode : RazorIRNode
{ {
public override IList<RazorIRNode> Children { get; } = EmptyArray; 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 namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{ {
internal class SetTagHelperPropertyIRNode : RazorIRNode public class SetTagHelperPropertyIRNode : RazorIRNode
{ {
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>(); public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution
public RazorSyntaxTree Execute(RazorCodeDocument codeDocument, RazorSyntaxTree syntaxTree) 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) if (resolver == null)
{ {
// No resolver, nothing to do. // 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Razor.Evolution; using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.AspNetCore.Razor.Evolution.Legacy; using Microsoft.AspNetCore.Razor.Evolution.Legacy;
@ -11,18 +10,9 @@ namespace Microsoft.CodeAnalysis.Razor
{ {
internal class DefaultTagHelperResolver : TagHelperResolver internal class DefaultTagHelperResolver : TagHelperResolver
{ {
private static readonly Version SupportedVCTHMvcVersion = new Version(1, 1); public DefaultTagHelperResolver(bool designTime)
private readonly string ViewComponentAssembly;
public DefaultTagHelperResolver(bool designTime) : this(designTime, ViewComponentTypes.Assembly)
{
}
// Internal for testing
internal DefaultTagHelperResolver(bool designTime, string viewComponentAssembly)
{ {
DesignTime = designTime; DesignTime = designTime;
ViewComponentAssembly = viewComponentAssembly;
} }
public bool DesignTime { get; } public bool DesignTime { get; }
@ -40,15 +30,8 @@ namespace Microsoft.CodeAnalysis.Razor
private void VisitTagHelpers(Compilation compilation, List<TagHelperDescriptor> results, ErrorSink errors) 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 types = new List<INamedTypeSymbol>();
var visitor = new TagHelperVisitor(@interface, types); var visitor = TagHelperTypeVisitor.Create(compilation, types);
VisitCompilation(visitor, compilation); VisitCompilation(visitor, compilation);
@ -63,20 +46,8 @@ namespace Microsoft.CodeAnalysis.Razor
private void VisitViewComponents(Compilation compilation, List<TagHelperDescriptor> results, ErrorSink errors) 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 types = new List<INamedTypeSymbol>();
var visitor = new ViewComponentVisitor(viewComponentAttributeSymbol, viewComponentAttributeSymbol, types); var visitor = ViewComponentTypeVisitor.Create(compilation, types);
VisitCompilation(visitor, compilation); 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" /> <Import Project="..\..\build\common.props" />
<PropertyGroup> <PropertyGroup>
<Description>Razor is a markup syntax for adding server-side logic to web pages. This package contains the Razor design-time infrastructure.</Description> <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> <TargetFrameworks>net451;netstandard1.3</TargetFrameworks>
@ -10,10 +8,9 @@
<PackageTags>aspnetcore;cshtml;razor</PackageTags> <PackageTags>aspnetcore;cshtml;razor</PackageTags>
<PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wp8+wpa81;</PackageTargetFallback> <PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wp8+wpa81;</PackageTargetFallback>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="1.3.0" /> <PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="1.3.0" />
<ProjectReference Include="..\Microsoft.AspNetCore.Razor.Evolution\Microsoft.AspNetCore.Razor.Evolution.csproj" /> <ProjectReference Include="..\Microsoft.AspNetCore.Razor.Evolution\Microsoft.AspNetCore.Razor.Evolution.csproj" />
<ProjectReference Include="..\Microsoft.CodeAnalysis.Razor\Microsoft.CodeAnalysis.Razor.csproj" />
</ItemGroup> </ItemGroup>
</Project> </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)) if (string.IsNullOrWhiteSpace(name))
{ {
var whitespaceError = Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidRestrictChildrenAttributeNameNullWhitespace( var whitespaceError = Resources.FormatTagHelperDescriptorFactory_InvalidRestrictChildrenAttributeNameNullWhitespace(
TagHelperTypes.RestrictChildrenAttribute, TagHelperTypes.RestrictChildrenAttribute,
tagHelperName); tagHelperName);
errorSink.OnError(SourceLocation.Zero, whitespaceError, length: 0); errorSink.OnError(SourceLocation.Zero, whitespaceError, length: 0);
} }
else if (TryValidateName( else if (TryValidateName(
name, name,
invalidCharacter => Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidRestrictChildrenAttributeName( invalidCharacter => Resources.FormatTagHelperDescriptorFactory_InvalidRestrictChildrenAttributeName(
TagHelperTypes.RestrictChildrenAttribute, TagHelperTypes.RestrictChildrenAttribute,
name, name,
tagHelperName, tagHelperName,
@ -372,15 +372,15 @@ namespace Microsoft.CodeAnalysis.Razor
} }
else if (string.IsNullOrWhiteSpace(parentTag)) else if (string.IsNullOrWhiteSpace(parentTag))
{ {
var error = Workspaces.Resources.FormatHtmlTargetElementAttribute_NameCannotBeNullOrWhitespace( var error = Resources.FormatHtmlTargetElementAttribute_NameCannotBeNullOrWhitespace(
Workspaces.Resources.TagHelperDescriptorFactory_ParentTag); Resources.TagHelperDescriptorFactory_ParentTag);
errorSink.OnError(SourceLocation.Zero, error, length: 0); errorSink.OnError(SourceLocation.Zero, error, length: 0);
return false; return false;
} }
else if (!TryValidateName( else if (!TryValidateName(
parentTag, parentTag,
invalidCharacter => Workspaces.Resources.FormatHtmlTargetElementAttribute_InvalidName( invalidCharacter => Resources.FormatHtmlTargetElementAttribute_InvalidName(
Workspaces.Resources.TagHelperDescriptorFactory_ParentTag.ToLower(), Resources.TagHelperDescriptorFactory_ParentTag.ToLower(),
parentTag, parentTag,
invalidCharacter), invalidCharacter),
errorSink)) errorSink))
@ -414,18 +414,18 @@ namespace Microsoft.CodeAnalysis.Razor
} }
var targetName = targetingAttributes ? var targetName = targetingAttributes ?
Workspaces.Resources.TagHelperDescriptorFactory_Attribute : Resources.TagHelperDescriptorFactory_Attribute :
Workspaces.Resources.TagHelperDescriptorFactory_Tag; Resources.TagHelperDescriptorFactory_Tag;
if (string.IsNullOrWhiteSpace(name)) if (string.IsNullOrWhiteSpace(name))
{ {
var error = Workspaces.Resources.FormatHtmlTargetElementAttribute_NameCannotBeNullOrWhitespace(targetName); var error = Resources.FormatHtmlTargetElementAttribute_NameCannotBeNullOrWhitespace(targetName);
errorSink.OnError(SourceLocation.Zero, error, length: 0); errorSink.OnError(SourceLocation.Zero, error, length: 0);
return false; return false;
} }
else if (!TryValidateName( else if (!TryValidateName(
name, name,
invalidCharacter => Workspaces.Resources.FormatHtmlTargetElementAttribute_InvalidName( invalidCharacter => Resources.FormatHtmlTargetElementAttribute_InvalidName(
targetName.ToLower(), targetName.ToLower(),
name, name,
invalidCharacter), invalidCharacter),
@ -509,7 +509,7 @@ namespace Microsoft.CodeAnalysis.Razor
// Specified HtmlAttributeNameAttribute.Name though property has no public setter. // Specified HtmlAttributeNameAttribute.Name though property has no public setter.
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameNotNullOrEmpty( Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameNotNullOrEmpty(
GetFullName(type), GetFullName(type),
property.Name, property.Name,
TagHelperTypes.HtmlAttributeNameAttribute, TagHelperTypes.HtmlAttributeNameAttribute,
@ -591,13 +591,13 @@ namespace Microsoft.CodeAnalysis.Razor
string nameOrPrefix; string nameOrPrefix;
if (attributeDescriptor.IsIndexer) if (attributeDescriptor.IsIndexer)
{ {
nameOrPrefix = Workspaces.Resources.TagHelperDescriptorFactory_Prefix; nameOrPrefix = Resources.TagHelperDescriptorFactory_Prefix;
} }
else if (string.IsNullOrEmpty(attributeDescriptor.Name)) else if (string.IsNullOrEmpty(attributeDescriptor.Name))
{ {
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameNullOrEmpty( Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameNullOrEmpty(
GetFullName(parentType), GetFullName(parentType),
attributeDescriptor.PropertyName), attributeDescriptor.PropertyName),
length: 0); length: 0);
@ -606,7 +606,7 @@ namespace Microsoft.CodeAnalysis.Razor
} }
else else
{ {
nameOrPrefix = Workspaces.Resources.TagHelperDescriptorFactory_Name; nameOrPrefix = Resources.TagHelperDescriptorFactory_Name;
} }
return ValidateTagHelperAttributeNameOrPrefix( 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. // Provide a single error if the entire name is whitespace, not an error per character.
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameOrPrefixWhitespace( Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameOrPrefixWhitespace(
GetFullName(parentType), GetFullName(parentType),
propertyName, propertyName,
nameOrPrefix), nameOrPrefix),
@ -654,7 +654,7 @@ namespace Microsoft.CodeAnalysis.Razor
{ {
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameOrPrefixStart( Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameOrPrefixStart(
GetFullName(parentType), GetFullName(parentType),
propertyName, propertyName,
nameOrPrefix, nameOrPrefix,
@ -672,7 +672,7 @@ namespace Microsoft.CodeAnalysis.Razor
{ {
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameOrPrefixCharacter( Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameOrPrefixCharacter(
GetFullName(parentType), GetFullName(parentType),
propertyName, propertyName,
nameOrPrefix, nameOrPrefix,
@ -749,7 +749,7 @@ namespace Microsoft.CodeAnalysis.Razor
isInvalid = true; isInvalid = true;
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributePrefixNotNull( Resources.FormatTagHelperDescriptorFactory_InvalidAttributePrefixNotNull(
GetFullName(parentType), GetFullName(parentType),
property.Name, property.Name,
TagHelperTypes.HtmlAttributeNameAttribute, TagHelperTypes.HtmlAttributeNameAttribute,
@ -764,7 +764,7 @@ namespace Microsoft.CodeAnalysis.Razor
isInvalid = true; isInvalid = true;
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameAttribute( Resources.FormatTagHelperDescriptorFactory_InvalidAttributeNameAttribute(
GetFullName(parentType), GetFullName(parentType),
property.Name, property.Name,
TagHelperTypes.HtmlAttributeNameAttribute, TagHelperTypes.HtmlAttributeNameAttribute,
@ -784,7 +784,7 @@ namespace Microsoft.CodeAnalysis.Razor
isInvalid = true; isInvalid = true;
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidAttributePrefixNull( Resources.FormatTagHelperDescriptorFactory_InvalidAttributePrefixNull(
GetFullName(parentType), GetFullName(parentType),
property.Name, property.Name,
TagHelperTypes.HtmlAttributeNameAttribute, TagHelperTypes.HtmlAttributeNameAttribute,
@ -973,7 +973,7 @@ namespace Microsoft.CodeAnalysis.Razor
{ {
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeCharacter(Current, _requiredAttributes), Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeCharacter(Current, _requiredAttributes),
length: 0); length: 0);
return false; return false;
} }
@ -1055,7 +1055,7 @@ namespace Microsoft.CodeAnalysis.Razor
{ {
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_PartialRequiredAttributeOperator(_requiredAttributes, op), Resources.FormatTagHelperDescriptorFactory_PartialRequiredAttributeOperator(_requiredAttributes, op),
length: 0); length: 0);
return null; return null;
} }
@ -1064,7 +1064,7 @@ namespace Microsoft.CodeAnalysis.Razor
{ {
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeOperator(Current, _requiredAttributes), Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeOperator(Current, _requiredAttributes),
length: 0); length: 0);
return null; return null;
} }
@ -1089,7 +1089,7 @@ namespace Microsoft.CodeAnalysis.Razor
{ {
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeMismatchedQuotes(_requiredAttributes, quote), Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeMismatchedQuotes(_requiredAttributes, quote),
length: 0); length: 0);
return null; return null;
} }
@ -1164,7 +1164,7 @@ namespace Microsoft.CodeAnalysis.Razor
{ {
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_CouldNotFindMatchingEndBrace(_requiredAttributes), Resources.FormatTagHelperDescriptorFactory_CouldNotFindMatchingEndBrace(_requiredAttributes),
length: 0); length: 0);
return null; return null;
} }
@ -1172,7 +1172,7 @@ namespace Microsoft.CodeAnalysis.Razor
{ {
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeCharacter(Current, _requiredAttributes), Resources.FormatTagHelperDescriptorFactory_InvalidRequiredAttributeCharacter(Current, _requiredAttributes),
length: 0); length: 0);
return null; return null;
} }
@ -1192,7 +1192,7 @@ namespace Microsoft.CodeAnalysis.Razor
{ {
errorSink.OnError( errorSink.OnError(
SourceLocation.Zero, SourceLocation.Zero,
Workspaces.Resources.FormatTagHelperDescriptorFactory_CouldNotFindMatchingEndBrace(_requiredAttributes), Resources.FormatTagHelperDescriptorFactory_CouldNotFindMatchingEndBrace(_requiredAttributes),
length: 0); length: 0);
return false; 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" /> <Import Project="..\..\build\common.props" />
<PropertyGroup> <PropertyGroup>
<Description>Razor is a markup syntax for adding server-side logic to web pages. This package contains the Razor design-time infrastructure.</Description> <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> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="1.3.0" /> <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" /> <ProjectReference Include="..\Microsoft.AspNetCore.Razor.Evolution\Microsoft.AspNetCore.Razor.Evolution.csproj" />
</ItemGroup> </ItemGroup>
</Project> </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 /> // <auto-generated />
namespace Microsoft.CodeAnalysis.Razor.Workspaces namespace Microsoft.CodeAnalysis.Razor
{ {
using System.Globalization; using System.Globalization;
using System.Reflection; using System.Reflection;
@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces
internal static class Resources internal static class Resources
{ {
private static readonly ResourceManager _resourceManager 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> /// <summary>
/// {0} cannot be null or an empty string. /// {0} cannot be null or an empty string.

View File

@ -1,5 +1,5 @@
// <auto-generated /> // <auto-generated />
namespace Microsoft.CodeAnalysis.Razor.Workspaces namespace Microsoft.CodeAnalysis.Razor
{ {
using System.Globalization; using System.Globalization;
using System.Reflection; using System.Reflection;
@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces
internal static class ViewComponentResources internal static class ViewComponentResources
{ {
private static readonly ResourceManager _resourceManager 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> /// <summary>
/// View component '{0}' must have exactly one public method named '{1}' or '{2}'. /// 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.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Evolution; using Microsoft.AspNetCore.Razor.Evolution;
using Microsoft.CodeAnalysis.Razor.Workspaces;
namespace Microsoft.CodeAnalysis.Razor 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. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.CodeAnalysis.Razor namespace Microsoft.CodeAnalysis.Razor
{ {
internal static class ViewComponentTypes internal static class ViewComponentTypes
{ {
public const string Assembly = "Microsoft.AspNetCore.Mvc.ViewFeatures"; 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 ViewComponentSuffix = "ViewComponent";
public const string ViewComponentAttribute = "Microsoft.AspNetCore.Mvc.ViewComponentAttribute"; public const string ViewComponentAttribute = "Microsoft.AspNetCore.Mvc.ViewComponentAttribute";

View File

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

View File

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

View File

@ -87,47 +87,47 @@ namespace Microsoft.AspNetCore.Razor.Evolution.IntegrationTests
WriteContentNode(node, node.Content); WriteContentNode(node, node.Content);
} }
internal override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node) public override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node)
{ {
WriteContentNode(node, node.UsedTagHelperTypeNames.ToArray()); 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)); 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); 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)); 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)); 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); 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)); 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)); 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); WriteContentNode(node, node.VariableName);
} }

View File

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

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // 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 System.Linq;
namespace Microsoft.AspNetCore.Razor.Evolution namespace Microsoft.AspNetCore.Razor.Evolution
@ -9,14 +10,19 @@ namespace Microsoft.AspNetCore.Razor.Evolution
{ {
public static IRazorEngineBuilder AddTagHelpers(this IRazorEngineBuilder builder, params TagHelperDescriptor[] tagHelpers) public static IRazorEngineBuilder AddTagHelpers(this IRazorEngineBuilder builder, params TagHelperDescriptor[] tagHelpers)
{ {
var resolver = (TestTagHelperDescriptorResolver)builder.Features.OfType<TagHelperFeature>().FirstOrDefault()?.Resolver; return AddTagHelpers(builder, (IEnumerable<TagHelperDescriptor>)tagHelpers);
if (resolver == null) }
public static IRazorEngineBuilder AddTagHelpers(this IRazorEngineBuilder builder, IEnumerable<TagHelperDescriptor> tagHelpers)
{
var feature = (TestTagHelperFeature)builder.Features.OfType<ITagHelperFeature>().FirstOrDefault();
if (feature == null)
{ {
resolver = new TestTagHelperDescriptorResolver(); feature = new TestTagHelperFeature();
builder.Features.Add(new TagHelperFeature(resolver)); builder.Features.Add(feature);
} }
resolver.TagHelpers.AddRange(tagHelpers); feature.TagHelpers.AddRange(tagHelpers);
return builder; return builder;
} }
} }

View File

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