diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultDocumentClassifier.cs b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultDocumentClassifier.cs index 5e0118cec4..2924c42a64 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultDocumentClassifier.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultDocumentClassifier.cs @@ -90,7 +90,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution _namespace.AddAfter(node); } - internal override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node) + public override void VisitDeclareTagHelperFields(DeclareTagHelperFieldsIRNode node) { _class.Insert(0, node); } diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultInstrumentationPass.cs b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultInstrumentationPass.cs index 83b2b9daf4..1681fc2105 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultInstrumentationPass.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultInstrumentationPass.cs @@ -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 diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorDesignTimeCSharpLoweringPhase.cs b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorDesignTimeCSharpLoweringPhase.cs index 8982b941e4..25562afee6 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorDesignTimeCSharpLoweringPhase.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorDesignTimeCSharpLoweringPhase.cs @@ -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) { diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorRuntimeCSharpLoweringPhase.cs b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorRuntimeCSharpLoweringPhase.cs index f54c297011..ff6121e830 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorRuntimeCSharpLoweringPhase.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/DefaultRazorRuntimeCSharpLoweringPhase.cs @@ -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(); diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/ITagHelperFeature.cs b/src/Microsoft.AspNetCore.Razor.Evolution/ITagHelperFeature.cs new file mode 100644 index 0000000000..faabf5b043 --- /dev/null +++ b/src/Microsoft.AspNetCore.Razor.Evolution/ITagHelperFeature.cs @@ -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; } + } +} diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/AddPreallocatedTagHelperHtmlAttributeIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/AddPreallocatedTagHelperHtmlAttributeIRNode.cs index f97878be0c..cfb7543547 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/AddPreallocatedTagHelperHtmlAttributeIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/AddPreallocatedTagHelperHtmlAttributeIRNode.cs @@ -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 Children { get; } = EmptyArray; diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/AddTagHelperHtmlAttributeIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/AddTagHelperHtmlAttributeIRNode.cs index 1a39c0ffe2..130ea9b693 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/AddTagHelperHtmlAttributeIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/AddTagHelperHtmlAttributeIRNode.cs @@ -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 Children { get; } = new List(); diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/CreateTagHelperIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/CreateTagHelperIRNode.cs index aaf3738dc2..393ee87721 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/CreateTagHelperIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/CreateTagHelperIRNode.cs @@ -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 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) { diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/DeclarePreallocatedTagHelperAttributeIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/DeclarePreallocatedTagHelperAttributeIRNode.cs index 18cc52d991..23b4ebd1a7 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/DeclarePreallocatedTagHelperAttributeIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/DeclarePreallocatedTagHelperAttributeIRNode.cs @@ -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 Children { get; } = EmptyArray; diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/DeclarePreallocatedTagHelperHtmlAttributeIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/DeclarePreallocatedTagHelperHtmlAttributeIRNode.cs index c4fc84bf40..bc3bb1c9e9 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/DeclarePreallocatedTagHelperHtmlAttributeIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/DeclarePreallocatedTagHelperHtmlAttributeIRNode.cs @@ -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 Children { get; } = EmptyArray; diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/DeclareTagHelperFieldsIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/DeclareTagHelperFieldsIRNode.cs index bd672cc344..2cd93e8059 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/DeclareTagHelperFieldsIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/DeclareTagHelperFieldsIRNode.cs @@ -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 Children { get; } = EmptyArray; diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/ExecuteTagHelpersIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/ExecuteTagHelpersIRNode.cs index 74954cd295..1317c0cbeb 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/ExecuteTagHelpersIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/ExecuteTagHelpersIRNode.cs @@ -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 Children { get; } = new List(); diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/InitializeTagHelperStructureIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/InitializeTagHelperStructureIRNode.cs index faa07e7825..dbff0c4b55 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/InitializeTagHelperStructureIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/InitializeTagHelperStructureIRNode.cs @@ -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 Children { get; } = new List(); diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/RazorIRNodeVisitor.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/RazorIRNodeVisitor.cs index 91e520e3ef..456140b6b8 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/RazorIRNodeVisitor.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/RazorIRNodeVisitor.cs @@ -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); } diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/RazorIRNodeVisitorOfT.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/RazorIRNodeVisitorOfT.cs index 288601a20f..400f02e9c1 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/RazorIRNodeVisitorOfT.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/RazorIRNodeVisitorOfT.cs @@ -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); } diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/SetPreallocatedTagHelperPropertyIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/SetPreallocatedTagHelperPropertyIRNode.cs index 654e44227a..b283af0e1b 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/SetPreallocatedTagHelperPropertyIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/SetPreallocatedTagHelperPropertyIRNode.cs @@ -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 Children { get; } = EmptyArray; diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/SetTagHelperPropertyIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/SetTagHelperPropertyIRNode.cs index c5904d1aac..c60727cbf9 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/SetTagHelperPropertyIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/SetTagHelperPropertyIRNode.cs @@ -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 Children { get; } = new List(); diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/TagHelperIRNode.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/TagHelperIRNode.cs index 67b5e8611f..6869f7d3b7 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/TagHelperIRNode.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Intermediate/TagHelperIRNode.cs @@ -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 Children { get; } = new List(); diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/ErrorSink.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/ErrorSink.cs index 7a37ab3159..78157ea37f 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/ErrorSink.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/ErrorSink.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy /// /// Used to manage s encountered during the Razor parsing phase. /// - internal class ErrorSink + public class ErrorSink { private readonly List _errors; diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/HtmlAttributeValueStyle.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/HtmlAttributeValueStyle.cs index 1391d3f703..2e13660d26 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/HtmlAttributeValueStyle.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/HtmlAttributeValueStyle.cs @@ -3,7 +3,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy { - internal enum HtmlAttributeValueStyle + public enum HtmlAttributeValueStyle { DoubleQuotes, SingleQuotes, diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/ITagHelperDescriptorResolver.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/ITagHelperDescriptorResolver.cs index 83d7540b51..af6c394de6 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/ITagHelperDescriptorResolver.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/ITagHelperDescriptorResolver.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution.Legacy /// /// Contract used to resolve s. /// - internal interface ITagHelperDescriptorResolver + public interface ITagHelperDescriptorResolver { IEnumerable Resolve(ErrorSink errorSink); } diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/RazorError.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/RazorError.cs index 9770413fcc..a67bfab440 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/RazorError.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Legacy/RazorError.cs @@ -7,7 +7,7 @@ using Microsoft.Extensions.Internal; namespace Microsoft.AspNetCore.Razor.Evolution.Legacy { - internal class RazorError : IEquatable + public class RazorError : IEquatable { internal static readonly RazorError[] EmptyArray = new RazorError[0]; diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.Razor.Evolution/Properties/AssemblyInfo.cs index 4d5c6c90b3..2043ddeaab 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/Properties/AssemblyInfo.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/Properties/AssemblyInfo.cs @@ -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")] diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/RazorPreallocatedTagHelperAttributePass.cs b/src/Microsoft.AspNetCore.Razor.Evolution/RazorPreallocatedTagHelperAttributePass.cs index 01d5ecbf79..90956c9576 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/RazorPreallocatedTagHelperAttributePass.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/RazorPreallocatedTagHelperAttributePass.cs @@ -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 || diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperBinderSyntaxTreePass.cs b/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperBinderSyntaxTreePass.cs index 0874f7c567..8fdb0467b9 100644 --- a/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperBinderSyntaxTreePass.cs +++ b/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperBinderSyntaxTreePass.cs @@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Razor.Evolution public RazorSyntaxTree Execute(RazorCodeDocument codeDocument, RazorSyntaxTree syntaxTree) { - var resolver = Engine.Features.OfType().FirstOrDefault()?.Resolver; + var resolver = Engine.Features.OfType().FirstOrDefault()?.Resolver; if (resolver == null) { // No resolver, nothing to do. diff --git a/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperFeature.cs b/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperFeature.cs deleted file mode 100644 index 363a74f731..0000000000 --- a/src/Microsoft.AspNetCore.Razor.Evolution/TagHelperFeature.cs +++ /dev/null @@ -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; } - } -} diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultTagHelperResolver.cs b/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultTagHelperResolver.cs index 3dfacaca05..9d2540d65b 100644 --- a/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultTagHelperResolver.cs +++ b/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultTagHelperResolver.cs @@ -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 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(); - 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 results, ErrorSink errors) { - var mvcViewFeaturesAssembly = compilation.References - .Select(reference => compilation.GetAssemblyOrModuleSymbol(reference)) - .OfType() - .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(); - 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 _results; - - public TagHelperVisitor(INamedTypeSymbol @interface, List 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 _results; - - public ViewComponentVisitor( - INamedTypeSymbol viewComponentAttribute, - INamedTypeSymbol nonViewComponentAttribute, - List results) - { - _viewComponentAttribute = viewComponentAttribute; - _nonViewComponentAttribute = nonViewComponentAttribute; - _results = results; - } - - public override void VisitNamedType(INamedTypeSymbol symbol) - { - if (IsViewComponent(symbol)) - { - _results.Add(symbol); - } - - if (symbol.DeclaredAccessibility != Accessibility.Public) - { - return; - } - - foreach (var member in symbol.GetTypeMembers()) - { - Visit(member); - } - } - - public override void VisitNamespace(INamespaceSymbol symbol) - { - foreach (var member in symbol.GetMembers()) - { - Visit(member); - } - } - - internal bool IsViewComponent(INamedTypeSymbol symbol) - { - if (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); - } - } } } \ No newline at end of file diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/Microsoft.CodeAnalysis.Razor.Workspaces.csproj b/src/Microsoft.CodeAnalysis.Razor.Workspaces/Microsoft.CodeAnalysis.Razor.Workspaces.csproj index 83e7761085..bdb9a23ccb 100644 --- a/src/Microsoft.CodeAnalysis.Razor.Workspaces/Microsoft.CodeAnalysis.Razor.Workspaces.csproj +++ b/src/Microsoft.CodeAnalysis.Razor.Workspaces/Microsoft.CodeAnalysis.Razor.Workspaces.csproj @@ -1,7 +1,5 @@ - - + - Razor is a markup syntax for adding server-side logic to web pages. This package contains the Razor design-time infrastructure. net451;netstandard1.3 @@ -10,10 +8,9 @@ aspnetcore;cshtml;razor $(PackageTargetFallback);portable-net45+win8+wp8+wpa81; - + - \ No newline at end of file diff --git a/src/Microsoft.CodeAnalysis.Razor/DefaultMetadataReferenceFeature.cs b/src/Microsoft.CodeAnalysis.Razor/DefaultMetadataReferenceFeature.cs new file mode 100644 index 0000000000..4226c336e0 --- /dev/null +++ b/src/Microsoft.CodeAnalysis.Razor/DefaultMetadataReferenceFeature.cs @@ -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 References { get; set; } + } +} diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultTagHelperDescriptorFactory.cs b/src/Microsoft.CodeAnalysis.Razor/DefaultTagHelperDescriptorFactory.cs similarity index 93% rename from src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultTagHelperDescriptorFactory.cs rename to src/Microsoft.CodeAnalysis.Razor/DefaultTagHelperDescriptorFactory.cs index 3b75645df0..203f27ea5d 100644 --- a/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultTagHelperDescriptorFactory.cs +++ b/src/Microsoft.CodeAnalysis.Razor/DefaultTagHelperDescriptorFactory.cs @@ -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; diff --git a/src/Microsoft.CodeAnalysis.Razor/DefaultTagHelperFeature.cs b/src/Microsoft.CodeAnalysis.Razor/DefaultTagHelperFeature.cs new file mode 100644 index 0000000000..3e072f6255 --- /dev/null +++ b/src/Microsoft.CodeAnalysis.Razor/DefaultTagHelperFeature.cs @@ -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().FirstOrDefault(); + Resolver = new InnerResolver(_referenceFeature); + } + + private class InnerResolver : ITagHelperDescriptorResolver + { + private readonly IMetadataReferenceFeature _referenceFeature; + + public InnerResolver(IMetadataReferenceFeature referenceFeature) + { + _referenceFeature = referenceFeature; + } + public IEnumerable Resolve(ErrorSink errorSink) + { + var compilation = CSharpCompilation.Create("__TagHelpers", references: _referenceFeature.References); + return TagHelpers.GetTagHelpers(compilation); + } + } + } +} diff --git a/src/Microsoft.CodeAnalysis.Razor/IMetadataReferenceFeature.cs b/src/Microsoft.CodeAnalysis.Razor/IMetadataReferenceFeature.cs new file mode 100644 index 0000000000..8d7254aae1 --- /dev/null +++ b/src/Microsoft.CodeAnalysis.Razor/IMetadataReferenceFeature.cs @@ -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 References { get; } + } +} diff --git a/src/Microsoft.CodeAnalysis.Razor/Microsoft.CodeAnalysis.Razor.csproj b/src/Microsoft.CodeAnalysis.Razor/Microsoft.CodeAnalysis.Razor.csproj index 61a59fb8bb..2c20866bc9 100644 --- a/src/Microsoft.CodeAnalysis.Razor/Microsoft.CodeAnalysis.Razor.csproj +++ b/src/Microsoft.CodeAnalysis.Razor/Microsoft.CodeAnalysis.Razor.csproj @@ -1,4 +1,4 @@ - + Razor is a markup syntax for adding server-side logic to web pages. This package contains the Razor design-time infrastructure. @@ -10,6 +10,7 @@ + \ No newline at end of file diff --git a/src/Microsoft.CodeAnalysis.Razor/Properties/AssemblyInfo.cs b/src/Microsoft.CodeAnalysis.Razor/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..e9e3dc9d90 --- /dev/null +++ b/src/Microsoft.CodeAnalysis.Razor/Properties/AssemblyInfo.cs @@ -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")] diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/Properties/Resources.Designer.cs b/src/Microsoft.CodeAnalysis.Razor/Properties/Resources.Designer.cs similarity index 99% rename from src/Microsoft.CodeAnalysis.Razor.Workspaces/Properties/Resources.Designer.cs rename to src/Microsoft.CodeAnalysis.Razor/Properties/Resources.Designer.cs index 12ea76a9a2..3b1139091e 100644 --- a/src/Microsoft.CodeAnalysis.Razor.Workspaces/Properties/Resources.Designer.cs +++ b/src/Microsoft.CodeAnalysis.Razor/Properties/Resources.Designer.cs @@ -1,5 +1,5 @@ // -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); /// /// {0} cannot be null or an empty string. diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/Properties/ViewComponentResources.Designer.cs b/src/Microsoft.CodeAnalysis.Razor/Properties/ViewComponentResources.Designer.cs similarity index 96% rename from src/Microsoft.CodeAnalysis.Razor.Workspaces/Properties/ViewComponentResources.Designer.cs rename to src/Microsoft.CodeAnalysis.Razor/Properties/ViewComponentResources.Designer.cs index 47b2e198ce..d2f1b85b09 100644 --- a/src/Microsoft.CodeAnalysis.Razor.Workspaces/Properties/ViewComponentResources.Designer.cs +++ b/src/Microsoft.CodeAnalysis.Razor/Properties/ViewComponentResources.Designer.cs @@ -1,5 +1,5 @@ // -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); /// /// View component '{0}' must have exactly one public method named '{1}' or '{2}'. diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/RazorLanguage.cs b/src/Microsoft.CodeAnalysis.Razor/RazorLanguage.cs similarity index 100% rename from src/Microsoft.CodeAnalysis.Razor.Workspaces/RazorLanguage.cs rename to src/Microsoft.CodeAnalysis.Razor/RazorLanguage.cs diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources.resx b/src/Microsoft.CodeAnalysis.Razor/Resources.resx similarity index 100% rename from src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources.resx rename to src/Microsoft.CodeAnalysis.Razor/Resources.resx diff --git a/src/Microsoft.CodeAnalysis.Razor/TagHelperTypeVisitor.cs b/src/Microsoft.CodeAnalysis.Razor/TagHelperTypeVisitor.cs new file mode 100644 index 0000000000..625e8284c1 --- /dev/null +++ b/src/Microsoft.CodeAnalysis.Razor/TagHelperTypeVisitor.cs @@ -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 _results; + + public static TagHelperTypeVisitor Create(Compilation compilation, List results) + { + var @interface = compilation.GetTypeByMetadataName(TagHelperTypes.ITagHelper); + return new TagHelperTypeVisitor(@interface, results); + } + + public TagHelperTypeVisitor(INamedTypeSymbol @interface, List 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); + } + } +} diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/TagHelperTypes.cs b/src/Microsoft.CodeAnalysis.Razor/TagHelperTypes.cs similarity index 100% rename from src/Microsoft.CodeAnalysis.Razor.Workspaces/TagHelperTypes.cs rename to src/Microsoft.CodeAnalysis.Razor/TagHelperTypes.cs diff --git a/src/Microsoft.CodeAnalysis.Razor/TagHelpers.cs b/src/Microsoft.CodeAnalysis.Razor/TagHelpers.cs new file mode 100644 index 0000000000..32e6de8055 --- /dev/null +++ b/src/Microsoft.CodeAnalysis.Razor/TagHelpers.cs @@ -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 GetTagHelpers(Compilation compilation) + { + var results = new List(); + var errors = new ErrorSink(); + + VisitTagHelpers(compilation, results, errors); + VisitViewComponents(compilation, results, errors); + + return results; + } + + private static void VisitTagHelpers(Compilation compilation, List results, ErrorSink errors) + { + var types = new List(); + 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 results, ErrorSink errors) + { + var types = new List(); + 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); + } + } + } + } +} diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/ViewComponentResources.resx b/src/Microsoft.CodeAnalysis.Razor/ViewComponentResources.resx similarity index 100% rename from src/Microsoft.CodeAnalysis.Razor.Workspaces/ViewComponentResources.resx rename to src/Microsoft.CodeAnalysis.Razor/ViewComponentResources.resx diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/ViewComponentTagHelperDescriptorFactory.cs b/src/Microsoft.CodeAnalysis.Razor/ViewComponentTagHelperDescriptorFactory.cs similarity index 99% rename from src/Microsoft.CodeAnalysis.Razor.Workspaces/ViewComponentTagHelperDescriptorFactory.cs rename to src/Microsoft.CodeAnalysis.Razor/ViewComponentTagHelperDescriptorFactory.cs index de1a3c2bed..966ac5865b 100644 --- a/src/Microsoft.CodeAnalysis.Razor.Workspaces/ViewComponentTagHelperDescriptorFactory.cs +++ b/src/Microsoft.CodeAnalysis.Razor/ViewComponentTagHelperDescriptorFactory.cs @@ -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 { diff --git a/src/Microsoft.CodeAnalysis.Razor/ViewComponentTypeVisitor.cs b/src/Microsoft.CodeAnalysis.Razor/ViewComponentTypeVisitor.cs new file mode 100644 index 0000000000..e689daca6a --- /dev/null +++ b/src/Microsoft.CodeAnalysis.Razor/ViewComponentTypeVisitor.cs @@ -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 _results; + + public static ViewComponentTypeVisitor Create(Compilation compilation, List 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 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); + } + } +} diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/ViewComponentTypes.cs b/src/Microsoft.CodeAnalysis.Razor/ViewComponentTypes.cs similarity index 91% rename from src/Microsoft.CodeAnalysis.Razor.Workspaces/ViewComponentTypes.cs rename to src/Microsoft.CodeAnalysis.Razor/ViewComponentTypes.cs index 93a5e93231..f7f7a560b3 100644 --- a/src/Microsoft.CodeAnalysis.Razor.Workspaces/ViewComponentTypes.cs +++ b/src/Microsoft.CodeAnalysis.Razor/ViewComponentTypes.cs @@ -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"; diff --git a/src/Microsoft.CodeAnalysis.Razor.Workspaces/XmlMemberDocumentation.cs b/src/Microsoft.CodeAnalysis.Razor/XmlMemberDocumentation.cs similarity index 98% rename from src/Microsoft.CodeAnalysis.Razor.Workspaces/XmlMemberDocumentation.cs rename to src/Microsoft.CodeAnalysis.Razor/XmlMemberDocumentation.cs index 3d17a50176..63685166cd 100644 --- a/src/Microsoft.CodeAnalysis.Razor.Workspaces/XmlMemberDocumentation.cs +++ b/src/Microsoft.CodeAnalysis.Razor/XmlMemberDocumentation.cs @@ -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 { diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/CodeGenerationIntegrationTest.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/CodeGenerationIntegrationTest.cs index bca7004242..66bb978915 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/CodeGenerationIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/CodeGenerationIntegrationTest.cs @@ -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(); diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/RazorIRNodeWriter.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/RazorIRNodeWriter.cs index 01174cf97e..38cab4d11f 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/RazorIRNodeWriter.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/IntegrationTests/RazorIRNodeWriter.cs @@ -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); } diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/Intermediate/DefaultRazorIRLoweringPhaseIntegrationTest.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/Intermediate/DefaultRazorIRLoweringPhaseIntegrationTest.cs index 2642af452c..e4cce08614 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/Intermediate/DefaultRazorIRLoweringPhaseIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/Intermediate/DefaultRazorIRLoweringPhaseIntegrationTest.cs @@ -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++) diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/RazorEngineBuilderExtensions.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/RazorEngineBuilderExtensions.cs index b2cf919a28..9cc84eb5d4 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/RazorEngineBuilderExtensions.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/RazorEngineBuilderExtensions.cs @@ -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().FirstOrDefault()?.Resolver; - if (resolver == null) + return AddTagHelpers(builder, (IEnumerable)tagHelpers); + } + + public static IRazorEngineBuilder AddTagHelpers(this IRazorEngineBuilder builder, IEnumerable tagHelpers) + { + var feature = (TestTagHelperFeature)builder.Features.OfType().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; } } diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TagHelperBinderSyntaxTreePassTest.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TagHelperBinderSyntaxTreePassTest.cs index 9b48ad700d..6d4590cd48 100644 --- a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TagHelperBinderSyntaxTreePassTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TagHelperBinderSyntaxTreePassTest.cs @@ -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()); }); 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(f => f.Resolver == resolver)); }); var pass = new TagHelperBinderSyntaxTreePass() diff --git a/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestTagHelperFeature.cs b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestTagHelperFeature.cs new file mode 100644 index 0000000000..e79f30e1ab --- /dev/null +++ b/test/Microsoft.AspNetCore.Razor.Evolution.Test/TestTagHelperFeature.cs @@ -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 tagHelpers) + { + Resolver = new TestTagHelperDescriptorResolver(tagHelpers); + } + + public RazorEngine Engine { get; set; } + + public List TagHelpers => ((TestTagHelperDescriptorResolver)Resolver).TagHelpers; + + public ITagHelperDescriptorResolver Resolver { get; } + } +} diff --git a/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/Comparers/CaseSensitiveTagHelperDescriptorComparer.cs b/test/Microsoft.CodeAnalysis.Razor.Test/Comparers/CaseSensitiveTagHelperDescriptorComparer.cs similarity index 100% rename from test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/Comparers/CaseSensitiveTagHelperDescriptorComparer.cs rename to test/Microsoft.CodeAnalysis.Razor.Test/Comparers/CaseSensitiveTagHelperDescriptorComparer.cs diff --git a/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/Comparers/CaseSensitiveTagHelperRequiredAttributeDescriptorComparer.cs b/test/Microsoft.CodeAnalysis.Razor.Test/Comparers/CaseSensitiveTagHelperRequiredAttributeDescriptorComparer.cs similarity index 100% rename from test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/Comparers/CaseSensitiveTagHelperRequiredAttributeDescriptorComparer.cs rename to test/Microsoft.CodeAnalysis.Razor.Test/Comparers/CaseSensitiveTagHelperRequiredAttributeDescriptorComparer.cs diff --git a/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/Comparers/TagHelperAttributeDescriptorComparer.cs b/test/Microsoft.CodeAnalysis.Razor.Test/Comparers/TagHelperAttributeDescriptorComparer.cs similarity index 100% rename from test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/Comparers/TagHelperAttributeDescriptorComparer.cs rename to test/Microsoft.CodeAnalysis.Razor.Test/Comparers/TagHelperAttributeDescriptorComparer.cs diff --git a/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/Comparers/TagHelperAttributeDesignTimeDescriptorComparer.cs b/test/Microsoft.CodeAnalysis.Razor.Test/Comparers/TagHelperAttributeDesignTimeDescriptorComparer.cs similarity index 100% rename from test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/Comparers/TagHelperAttributeDesignTimeDescriptorComparer.cs rename to test/Microsoft.CodeAnalysis.Razor.Test/Comparers/TagHelperAttributeDesignTimeDescriptorComparer.cs diff --git a/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/Comparers/TagHelperDesignTimeDescriptorComparer.cs b/test/Microsoft.CodeAnalysis.Razor.Test/Comparers/TagHelperDesignTimeDescriptorComparer.cs similarity index 100% rename from test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/Comparers/TagHelperDesignTimeDescriptorComparer.cs rename to test/Microsoft.CodeAnalysis.Razor.Test/Comparers/TagHelperDesignTimeDescriptorComparer.cs diff --git a/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/DefaultTagHelperDescriptorFactoryTest.cs b/test/Microsoft.CodeAnalysis.Razor.Test/DefaultTagHelperDescriptorFactoryTest.cs similarity index 100% rename from test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/DefaultTagHelperDescriptorFactoryTest.cs rename to test/Microsoft.CodeAnalysis.Razor.Test/DefaultTagHelperDescriptorFactoryTest.cs diff --git a/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/TagHelperDescriptorFactoryTagHelpers.cs b/test/Microsoft.CodeAnalysis.Razor.Test/TagHelperDescriptorFactoryTagHelpers.cs similarity index 100% rename from test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/TagHelperDescriptorFactoryTagHelpers.cs rename to test/Microsoft.CodeAnalysis.Razor.Test/TagHelperDescriptorFactoryTagHelpers.cs diff --git a/test/Microsoft.CodeAnalysis.Razor.Test/TagHelperTypeVisitorTest.cs b/test/Microsoft.CodeAnalysis.Razor.Test/TagHelperTypeVisitorTest.cs new file mode 100644 index 0000000000..16993b2a11 --- /dev/null +++ b/test/Microsoft.CodeAnalysis.Razor.Test/TagHelperTypeVisitorTest.cs @@ -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()); + 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()); + 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()); + 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()); + 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()); + 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 : TagHelper + { + } + + internal class Invalid_InternalTagHelper : TagHelper + { + } + + public class Valid_PlainTagHelper : TagHelper + { + } + + public class Valid_InheritedTagHelper : Valid_PlainTagHelper + { + } +} diff --git a/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/TestCompilation.cs b/test/Microsoft.CodeAnalysis.Razor.Test/TestCompilation.cs similarity index 94% rename from test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/TestCompilation.cs rename to test/Microsoft.CodeAnalysis.Razor.Test/TestCompilation.cs index b6457fdbf1..76d8981221 100644 --- a/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/TestCompilation.cs +++ b/test/Microsoft.CodeAnalysis.Razor.Test/TestCompilation.cs @@ -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 { diff --git a/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ViewComponentTagHelperDescriptorFactoryTest.cs b/test/Microsoft.CodeAnalysis.Razor.Test/ViewComponentTagHelperDescriptorFactoryTest.cs similarity index 100% rename from test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ViewComponentTagHelperDescriptorFactoryTest.cs rename to test/Microsoft.CodeAnalysis.Razor.Test/ViewComponentTagHelperDescriptorFactoryTest.cs diff --git a/test/Microsoft.CodeAnalysis.Razor.Test/ViewComponentTypeVisitorTest.cs b/test/Microsoft.CodeAnalysis.Razor.Test/ViewComponentTypeVisitorTest.cs new file mode 100644 index 0000000000..a28d0d7c63 --- /dev/null +++ b/test/Microsoft.CodeAnalysis.Razor.Test/ViewComponentTypeVisitorTest.cs @@ -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()); + 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()); + 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()); + 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()); + 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()); + 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()); + 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()); + 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()); + 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 + { + } + + 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 + { + } + } +} diff --git a/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/DefaultTagHelperResolverTest.cs b/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/DefaultTagHelperResolverTest.cs deleted file mode 100644 index 8c2ef107ac..0000000000 --- a/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/DefaultTagHelperResolverTest.cs +++ /dev/null @@ -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()); - 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()); - 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()); - 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()); - 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()); - 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()); - 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()); - 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()); - 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()); - 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()); - 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()); - 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()); - 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()); - 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 : 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 - { - } - - 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 - { - } -}