diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.Designer.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.Designer.cs
index 3a7ce3183a..5d4e39e752 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.Designer.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.Designer.cs
@@ -223,7 +223,7 @@ namespace Microsoft.AspNetCore.Razor.Language {
}
///
- /// Looks up a localized string similar to The '@{0}' directive specified in {1} file will not be imported. The directive must appear at the top of each Razor cshtml file.
+ /// Looks up a localized string similar to The '@{0}' directive specified in {1} file will not be imported. The directive must appear at the top of each Razor file.
///
internal static string PageDirectiveCannotBeImported {
get {
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.resx b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.resx
index 3fe9868ecd..4a27c934ae 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.resx
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/ComponentResources.resx
@@ -163,7 +163,7 @@
TypeName
- The '@{0}' directive specified in {1} file will not be imported. The directive must appear at the top of each Razor cshtml file
+ The '@{0}' directive specified in {1} file will not be imported. The directive must appear at the top of each Razor file
Mark the page as a routable component.
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDiagnosticFactory.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDiagnosticFactory.cs
index ba2f30fa2b..42a7b4bdaf 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDiagnosticFactory.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDiagnosticFactory.cs
@@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
public static readonly RazorDiagnosticDescriptor UnsupportedTagHelperDirective = new RazorDiagnosticDescriptor(
$"{DiagnosticPrefix}9978",
() =>
- "The directives @addTagHelper, @removeTagHelper and @tagHelperPrefix are not valid in a component document." +
+ "The directives @addTagHelper, @removeTagHelper and @tagHelperPrefix are not valid in a component document. " +
"Use '@using ' directive instead.",
RazorDiagnosticSeverity.Error);
@@ -321,5 +321,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
{
return RazorDiagnostic.Create(ChildContentHasInvalidParameterOnComponent, source ?? SourceSpan.Undefined, attribute, element);
}
+
+ public static readonly RazorDiagnosticDescriptor UnsupportedComponentImportContent =
+ new RazorDiagnosticDescriptor(
+ $"{DiagnosticPrefix}10003",
+ () => "Markup, code and block directives are not valid in component imports.",
+ RazorDiagnosticSeverity.Error);
+
+ public static RazorDiagnostic Create_UnsupportedComponentImportContent(SourceSpan? source)
+ {
+ return RazorDiagnostic.Create(UnsupportedComponentImportContent, source ?? SourceSpan.Undefined);
+ }
}
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDocumentClassifierPass.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDocumentClassifierPass.cs
index 1fa21843f7..37d44227df 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDocumentClassifierPass.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentDocumentClassifierPass.cs
@@ -70,47 +70,63 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
}
@namespace.Content = computedNamespace;
-
- @class.BaseType = ComponentsApi.ComponentBase.FullTypeName;
@class.ClassName = computedClass;
@class.Modifiers.Clear();
@class.Modifiers.Add("public");
- var documentNode = codeDocument.GetDocumentIntermediateNode();
- var typeParamReferences = documentNode.FindDirectiveReferences(ComponentTypeParamDirective.Directive);
- for (var i = 0; i < typeParamReferences.Count; i++)
+ if (FileKinds.IsComponentImport(codeDocument.GetFileKind()))
{
- var typeParamNode = (DirectiveIntermediateNode)typeParamReferences[i].Node;
- if (typeParamNode.HasDiagnostics)
+ // We don't want component imports to be considered as real component.
+ // But we still want to generate code for it so we can get diagnostics.
+ @class.BaseType = typeof(object).FullName;
+
+ method.ReturnType = "void";
+ method.MethodName = "Execute";
+ method.Modifiers.Clear();
+ method.Modifiers.Add("protected");
+
+ method.Parameters.Clear();
+ }
+ else
+ {
+ @class.BaseType = ComponentsApi.ComponentBase.FullTypeName;
+
+ var documentNode = codeDocument.GetDocumentIntermediateNode();
+ var typeParamReferences = documentNode.FindDirectiveReferences(ComponentTypeParamDirective.Directive);
+ for (var i = 0; i < typeParamReferences.Count; i++)
{
- continue;
+ var typeParamNode = (DirectiveIntermediateNode)typeParamReferences[i].Node;
+ if (typeParamNode.HasDiagnostics)
+ {
+ continue;
+ }
+
+ @class.TypeParameters.Add(new TypeParameter() { ParameterName = typeParamNode.Tokens.First().Content, });
}
- @class.TypeParameters.Add(new TypeParameter() { ParameterName = typeParamNode.Tokens.First().Content, });
+ method.ReturnType = "void";
+ method.MethodName = ComponentsApi.ComponentBase.BuildRenderTree;
+ method.Modifiers.Clear();
+ method.Modifiers.Add("protected");
+ method.Modifiers.Add("override");
+
+ method.Parameters.Clear();
+ method.Parameters.Add(new MethodParameter()
+ {
+ ParameterName = "builder",
+ TypeName = ComponentsApi.RenderTreeBuilder.FullTypeName,
+ });
+
+ // We need to call the 'base' method as the first statement.
+ var callBase = new CSharpCodeIntermediateNode();
+ callBase.Annotations.Add(BuildRenderTreeBaseCallAnnotation, true);
+ callBase.Children.Add(new IntermediateToken
+ {
+ Kind = TokenKind.CSharp,
+ Content = $"base.{ComponentsApi.ComponentBase.BuildRenderTree}(builder);"
+ });
+ method.Children.Insert(0, callBase);
}
-
- method.ReturnType = "void";
- method.MethodName = ComponentsApi.ComponentBase.BuildRenderTree;
- method.Modifiers.Clear();
- method.Modifiers.Add("protected");
- method.Modifiers.Add("override");
-
- method.Parameters.Clear();
- method.Parameters.Add(new MethodParameter()
- {
- ParameterName = "builder",
- TypeName = ComponentsApi.RenderTreeBuilder.FullTypeName,
- });
-
- // We need to call the 'base' method as the first statement.
- var callBase = new CSharpCodeIntermediateNode();
- callBase.Annotations.Add(BuildRenderTreeBaseCallAnnotation, true);
- callBase.Children.Add(new IntermediateToken
- {
- Kind = TokenKind.CSharp,
- Content = $"base.{ComponentsApi.ComponentBase.BuildRenderTree}(builder);"
- });
- method.Children.Insert(0, callBase);
}
internal static bool IsBuildRenderTreeBaseCall(CSharpCodeIntermediateNode node)
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentInjectDirective.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentInjectDirective.cs
index 7d123442ad..1af26eb508 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentInjectDirective.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentInjectDirective.cs
@@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
throw new ArgumentNullException(nameof(builder));
}
- builder.AddDirective(FileKinds.Component, Directive);
+ builder.AddDirective(Directive, FileKinds.Component, FileKinds.ComponentImport);
builder.Features.Add(new ComponentInjectDirectivePass());
}
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentLayoutDirective.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentLayoutDirective.cs
index c746b75d7b..394bed3b56 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentLayoutDirective.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentLayoutDirective.cs
@@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
throw new ArgumentNullException(nameof(builder));
}
- builder.AddDirective(FileKinds.Component, Directive);
+ builder.AddDirective(Directive, FileKinds.Component, FileKinds.ComponentImport);
builder.Features.Add(new ComponentLayoutDirectivePass());
}
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentLayoutDirectivePass.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentLayoutDirectivePass.cs
index b1c36f3152..244c95df78 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentLayoutDirectivePass.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentLayoutDirectivePass.cs
@@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
attributeNode.Children.Add(new IntermediateToken()
{
Kind = TokenKind.CSharp,
- Content = $"[{ComponentsApi.LayoutAttribute.FullTypeName}(typeof({token.Content}))]" + Environment.NewLine,
+ Content = $"[{ComponentsApi.LayoutAttribute.FullTypeName}(typeof({token.Content}))]",
});
// Insert the new attribute on top of the class
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentPageDirective.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentPageDirective.cs
index 80ebd9ffca..8fefd172f8 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentPageDirective.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentPageDirective.cs
@@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
throw new ArgumentNullException(nameof(builder));
}
- builder.AddDirective(FileKinds.Component, Directive);
+ builder.AddDirective(Directive, FileKinds.Component, FileKinds.ComponentImport);
builder.Features.Add(new ComponentPageDirectivePass());
return builder;
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentPageDirectivePass.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentPageDirectivePass.cs
index 0fe0ac5e26..c751dd57b3 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentPageDirectivePass.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentPageDirectivePass.cs
@@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
for (var i = 0; i < directives.Count; i++)
{
var directive = directives[i];
- if (directive.Node.IsImported())
+ if (FileKinds.IsComponentImport(codeDocument.GetFileKind()) || directive.Node.IsImported())
{
directive.Node.Diagnostics.Add(ComponentDiagnosticFactory.CreatePageDirective_CannotBeImported(directive.Node.Source.Value));
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentTypeParamDirective.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentTypeParamDirective.cs
index d0e3c12627..d37f84a0df 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentTypeParamDirective.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Components/ComponentTypeParamDirective.cs
@@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
throw new ArgumentNullException(nameof(builder));
}
- builder.AddDirective(FileKinds.Component, Directive);
+ builder.AddDirective(Directive, FileKinds.Component, FileKinds.ComponentImport);
return builder;
}
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorDirectiveFeature.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorDirectiveFeature.cs
index f766b4b14a..05dd57ebf1 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorDirectiveFeature.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorDirectiveFeature.cs
@@ -9,7 +9,21 @@ namespace Microsoft.AspNetCore.Razor.Language
{
internal class DefaultRazorDirectiveFeature : RazorEngineFeatureBase, IRazorDirectiveFeature, IConfigureRazorParserOptionsFeature
{
- public ICollection Directives { get; } = new List();
+ // To maintain backwards compatibility, adding to this list will default to legacy file kind.
+ public ICollection Directives
+ {
+ get
+ {
+ ICollection result;
+ if (!DirectivesByFileKind.TryGetValue(FileKinds.Legacy, out result))
+ {
+ result = new List();
+ DirectivesByFileKind.Add(FileKinds.Legacy, result);
+ }
+
+ return result;
+ }
+ }
public IDictionary> DirectivesByFileKind { get; } = new Dictionary>(StringComparer.OrdinalIgnoreCase);
@@ -24,22 +38,11 @@ namespace Microsoft.AspNetCore.Razor.Language
options.Directives.Clear();
- foreach (var directive in Directives)
- {
- options.Directives.Add(directive);
- }
-
- if (options.FileKind != null && DirectivesByFileKind.TryGetValue(options.FileKind, out var directives))
+ var fileKind = options.FileKind ?? FileKinds.Legacy;
+ if (DirectivesByFileKind.TryGetValue(fileKind, out var directives))
{
foreach (var directive in directives)
{
- // Replace any non-file-kind-specific directives
- var replaces = options.Directives.Where(d => string.Equals(d.Directive, directive.Directive, StringComparison.Ordinal)).ToArray();
- foreach (var replace in replaces)
- {
- options.Directives.Remove(replace);
- }
-
options.Directives.Add(directive);
}
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorIntermediateNodeLoweringPhase.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorIntermediateNodeLoweringPhase.cs
index 38f05d593b..232ce738fb 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorIntermediateNodeLoweringPhase.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorIntermediateNodeLoweringPhase.cs
@@ -45,7 +45,17 @@ namespace Microsoft.AspNetCore.Razor.Language
// We need to decide up front if this document is a "component" file. This will affect how
// lowering behaves.
LoweringVisitor visitor;
- if (FileKinds.IsComponent(codeDocument.GetFileKind()) &&
+ if (FileKinds.IsComponentImport(codeDocument.GetFileKind()) &&
+ syntaxTree.Options.FeatureFlags.AllowComponentFileKind)
+ {
+ visitor = new ComponentImportFileKindVisitor(document, builder, syntaxTree.Options.FeatureFlags)
+ {
+ SourceDocument = syntaxTree.Source,
+ };
+
+ visitor.Visit(syntaxTree.Root);
+ }
+ else if (FileKinds.IsComponent(codeDocument.GetFileKind()) &&
syntaxTree.Options.FeatureFlags.AllowComponentFileKind)
{
visitor = new ComponentFileKindVisitor(document, builder, syntaxTree.Options.FeatureFlags)
@@ -1856,6 +1866,58 @@ namespace Microsoft.AspNetCore.Razor.Language
}
}
+ private class ComponentImportFileKindVisitor : LoweringVisitor
+ {
+ public ComponentImportFileKindVisitor(
+ DocumentIntermediateNode document,
+ IntermediateNodeBuilder builder,
+ RazorParserFeatureFlags featureFlags)
+ : base(document, builder, featureFlags)
+ {
+ }
+
+ public override void DefaultVisit(SyntaxNode node)
+ {
+ base.DefaultVisit(node);
+ }
+
+ public override void VisitMarkupElement(MarkupElementSyntax node)
+ {
+ _document.Diagnostics.Add(
+ ComponentDiagnosticFactory.Create_UnsupportedComponentImportContent(BuildSourceSpanFromNode(node)));
+ }
+
+ public override void VisitMarkupCommentBlock(MarkupCommentBlockSyntax node)
+ {
+ _document.Diagnostics.Add(
+ ComponentDiagnosticFactory.Create_UnsupportedComponentImportContent(BuildSourceSpanFromNode(node)));
+ }
+
+ public override void VisitMarkupTagHelperElement(MarkupTagHelperElementSyntax node)
+ {
+ _document.Diagnostics.Add(
+ ComponentDiagnosticFactory.Create_UnsupportedComponentImportContent(BuildSourceSpanFromNode(node)));
+ }
+
+ public override void VisitCSharpImplicitExpression(CSharpImplicitExpressionSyntax node)
+ {
+ _document.Diagnostics.Add(
+ ComponentDiagnosticFactory.Create_UnsupportedComponentImportContent(BuildSourceSpanFromNode(node)));
+ }
+
+ public override void VisitCSharpExplicitExpression(CSharpExplicitExpressionSyntax node)
+ {
+ _document.Diagnostics.Add(
+ ComponentDiagnosticFactory.Create_UnsupportedComponentImportContent(BuildSourceSpanFromNode(node)));
+ }
+
+ public override void VisitCSharpStatement(CSharpStatementSyntax node)
+ {
+ _document.Diagnostics.Add(
+ ComponentDiagnosticFactory.Create_UnsupportedComponentImportContent(BuildSourceSpanFromNode(node)));
+ }
+ }
+
private class ImportsVisitor : LoweringVisitor
{
public ImportsVisitor(DocumentIntermediateNode document, IntermediateNodeBuilder builder, RazorParserFeatureFlags featureFlags)
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorTagHelperBinderPhase.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorTagHelperBinderPhase.cs
index 34a2d77613..e4a30a841a 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorTagHelperBinderPhase.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/DefaultRazorTagHelperBinderPhase.cs
@@ -37,7 +37,9 @@ namespace Microsoft.AspNetCore.Razor.Language
// The imports come logically before the main razor file and are in the order they
// should be processed.
DirectiveVisitor visitor = null;
- if (FileKinds.IsComponent(codeDocument.GetFileKind()))
+ var parserOptions = codeDocument.GetParserOptions();
+ if (FileKinds.IsComponent(codeDocument.GetFileKind()) &&
+ (parserOptions == null || parserOptions.FeatureFlags.AllowComponentFileKind))
{
codeDocument.TryComputeNamespaceAndClass(out var currentNamespace, out var _);
visitor = new ComponentDirectiveVisitor(codeDocument.Source.FilePath, descriptors, currentNamespace);
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/FunctionsDirective.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/FunctionsDirective.cs
index 630272cdef..8947e20134 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/FunctionsDirective.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/FunctionsDirective.cs
@@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
throw new ArgumentNullException(nameof(builder));
}
- builder.AddDirective(Directive);
+ builder.AddDirective(Directive, FileKinds.Legacy, FileKinds.Component);
builder.Features.Add(new FunctionsDirectivePass());
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ImplementsDirective.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ImplementsDirective.cs
index b160ff8773..4ee1657a27 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ImplementsDirective.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/ImplementsDirective.cs
@@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
throw new ArgumentNullException(nameof(builder));
}
- builder.AddDirective(Directive);
+ builder.AddDirective(Directive, FileKinds.Legacy, FileKinds.Component, FileKinds.ComponentImport);
builder.Features.Add(new ImplementsDirectivePass());
}
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/InheritsDirective.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/InheritsDirective.cs
index 12cdb3708a..74fa396bcc 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/InheritsDirective.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/InheritsDirective.cs
@@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
throw new ArgumentNullException(nameof(builder));
}
- builder.AddDirective(Directive);
+ builder.AddDirective(Directive, FileKinds.Legacy, FileKinds.Component, FileKinds.ComponentImport);
builder.Features.Add(new InheritsDirectivePass());
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/SectionDirective.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/SectionDirective.cs
index b1f8633122..9040e18688 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/SectionDirective.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/Extensions/SectionDirective.cs
@@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
throw new ArgumentNullException(nameof(builder));
}
- builder.AddDirective(Directive);
+ builder.AddDirective(Directive, FileKinds.Legacy, FileKinds.Component);
builder.Features.Add(new SectionDirectivePass());
builder.AddTargetExtension(new SectionTargetExtension());
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/FileKinds.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/FileKinds.cs
index c69df04e60..605c601cc7 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/FileKinds.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/FileKinds.cs
@@ -27,6 +27,23 @@ namespace Microsoft.AspNetCore.Razor.Language
return string.Equals(fileKind, FileKinds.ComponentImport, StringComparison.OrdinalIgnoreCase);
}
+ public static string GetComponentFileKindFromFilePath(string filePath)
+ {
+ if (filePath == null)
+ {
+ throw new ArgumentNullException(nameof(filePath));
+ }
+
+ if (string.Equals(ComponentMetadata.ImportsFileName, Path.GetFileName(filePath), StringComparison.Ordinal))
+ {
+ return FileKinds.ComponentImport;
+ }
+ else
+ {
+ return FileKinds.Component;
+ }
+ }
+
public static string GetFileKindFromFilePath(string filePath)
{
if (filePath == null)
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorProjectEngineBuilderExtensions.cs b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorProjectEngineBuilderExtensions.cs
index 09fdf087f4..89e809fb09 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorProjectEngineBuilderExtensions.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Language/src/RazorProjectEngineBuilderExtensions.cs
@@ -166,35 +166,38 @@ namespace Microsoft.AspNetCore.Razor.Language
/// Adds the specified for the provided file kind.
///
/// The .
- /// The file kind, for which to register the directive. See .
/// The to add.
+ /// The file kinds, for which to register the directive. See .
/// The .
- public static RazorProjectEngineBuilder AddDirective(this RazorProjectEngineBuilder builder, string fileKind, DirectiveDescriptor directive)
+ public static RazorProjectEngineBuilder AddDirective(this RazorProjectEngineBuilder builder, DirectiveDescriptor directive, params string[] fileKinds)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
- if (fileKind == null)
- {
- throw new ArgumentNullException(nameof(fileKind));
- }
-
if (directive == null)
{
throw new ArgumentNullException(nameof(directive));
}
- var directiveFeature = GetDirectiveFeature(builder);
-
- if (!directiveFeature.DirectivesByFileKind.TryGetValue(fileKind, out var directives))
+ if (fileKinds == null)
{
- directives = new List();
- directiveFeature.DirectivesByFileKind.Add(fileKind, directives);
+ throw new ArgumentNullException(nameof(fileKinds));
}
- directives.Add(directive);
+ var directiveFeature = GetDirectiveFeature(builder);
+
+ foreach (var fileKind in fileKinds)
+ {
+ if (!directiveFeature.DirectivesByFileKind.TryGetValue(fileKind, out var directives))
+ {
+ directives = new List();
+ directiveFeature.DirectivesByFileKind.Add(fileKind, directives);
+ }
+
+ directives.Add(directive);
+ }
return builder;
}
diff --git a/src/Razor/Microsoft.AspNetCore.Razor.Tools/src/GenerateCommand.cs b/src/Razor/Microsoft.AspNetCore.Razor.Tools/src/GenerateCommand.cs
index 3501096bde..5715739c67 100644
--- a/src/Razor/Microsoft.AspNetCore.Razor.Tools/src/GenerateCommand.cs
+++ b/src/Razor/Microsoft.AspNetCore.Razor.Tools/src/GenerateCommand.cs
@@ -7,6 +7,7 @@ using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
+using Microsoft.AspNetCore.Razor.Language.Components;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.Extensions.CommandLineUtils;
@@ -286,6 +287,10 @@ namespace Microsoft.AspNetCore.Razor.Tools
{
var outputPath = Path.Combine(projectDirectory, outputs[i]);
var fileKind = fileKinds.Count > 0 ? fileKinds[i] : "mvc";
+ if (Language.FileKinds.IsComponent(fileKind))
+ {
+ fileKind = Language.FileKinds.GetComponentFileKindFromFilePath(sources[i]);
+ }
items[i] = new SourceItem(sources[i], outputs[i], relativePath[i], fileKind);
}
diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/RazorIntegrationTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/RazorIntegrationTestBase.cs
index 75440d18f4..5266adac10 100644
--- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/RazorIntegrationTestBase.cs
+++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common/Language/IntegrationTests/RazorIntegrationTestBase.cs
@@ -59,6 +59,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
{
AdditionalSyntaxTrees = new List();
AdditionalRazorItems = new List();
+ ImportItems = new List();
BaseCompilation = DefaultBaseCompilation;
Configuration = RazorConfiguration.Default;
@@ -72,6 +73,8 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
internal List AdditionalRazorItems { get; }
+ internal List ImportItems { get; }
+
internal List AdditionalSyntaxTrees { get; }
internal virtual CSharpCompilation BaseCompilation { get; }
@@ -118,6 +121,8 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
// Turn off checksums, we're testing code generation.
b.Features.Add(new SuppressChecksum());
+ b.Features.Add(new TestImportProjectFeature(ImportItems));
+
if (LineEnding != null)
{
b.Phases.Insert(0, new ForceLineEndingPhase(LineEnding));
@@ -135,7 +140,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
});
}
- internal RazorProjectItem CreateProjectItem(string cshtmlRelativePath, string cshtmlContent)
+ internal RazorProjectItem CreateProjectItem(string cshtmlRelativePath, string cshtmlContent, string fileKind = null)
{
var fullPath = WorkingDirectory + PathSeparator + cshtmlRelativePath;
@@ -156,7 +161,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
physicalPath: fullPath,
relativePhysicalPath: cshtmlRelativePath,
basePath: WorkingDirectory,
- fileKind: FileKind)
+ fileKind: fileKind ?? FileKind)
{
Content = cshtmlContent.TrimStart(),
};
@@ -167,7 +172,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
return CompileToCSharp(DefaultFileName, cshtmlContent, throwOnFailure);
}
- protected CompileToCSharpResult CompileToCSharp(string cshtmlRelativePath, string cshtmlContent, bool throwOnFailure = true)
+ protected CompileToCSharpResult CompileToCSharp(string cshtmlRelativePath, string cshtmlContent, bool throwOnFailure = true, string fileKind = null)
{
if (DeclarationOnly && DesignTime)
{
@@ -197,7 +202,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
}
// Result of generating declarations
- var projectItem = CreateProjectItem(cshtmlRelativePath, cshtmlContent);
+ var projectItem = CreateProjectItem(cshtmlRelativePath, cshtmlContent, fileKind);
codeDocument = projectEngine.ProcessDeclarationOnly(projectItem);
var declaration = new CompileToCSharpResult
{
@@ -243,7 +248,7 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
// This will include the built-in components.
var projectEngine = CreateProjectEngine(Configuration, BaseCompilation.References.ToArray());
- var projectItem = CreateProjectItem(cshtmlRelativePath, cshtmlContent);
+ var projectItem = CreateProjectItem(cshtmlRelativePath, cshtmlContent, fileKind);
RazorCodeDocument codeDocument;
if (DeclarationOnly)
@@ -456,5 +461,22 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
codeDocument.Items[key] = LineEnding;
}
}
+
+ private class TestImportProjectFeature : IImportProjectFeature
+ {
+ private List _imports;
+
+ public TestImportProjectFeature(List imports)
+ {
+ _imports = imports;
+ }
+
+ public RazorProjectEngine ProjectEngine { get; set; }
+
+ public IReadOnlyList GetImports(RazorProjectItem projectItem)
+ {
+ return _imports;
+ }
+ }
}
}