Flow FileKind from project items -> code document
This is a bit of a rework of how we initially set this up, but with more
forethought to how this will work in the project system. I have not yet
surfaced this through VS.
My immediate next step is to light up the component integration tests
and something like this is on the critical path to get that work since
we need a way to specify in tests that a document should be treated as
a component.
\n\nCommit migrated from 6b81da3f02
This commit is contained in:
parent
ceb1189b2e
commit
c37dada0dc
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Components
|
|||
|
||||
protected override bool IsMatch(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||
{
|
||||
return codeDocument.GetInputDocumentKind() == InputDocumentKind.Component;
|
||||
return string.Equals(codeDocument.GetFileKind(), FileKinds.Component);
|
||||
}
|
||||
|
||||
protected override void OnDocumentStructureCreated(RazorCodeDocument codeDocument, NamespaceDeclarationIntermediateNode @namespace, ClassDeclarationIntermediateNode @class, MethodDeclarationIntermediateNode method)
|
||||
|
|
|
|||
|
|
@ -68,10 +68,10 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
var importItems = importFeature.GetImports(projectItem);
|
||||
var importSourceDocuments = GetImportSourceDocuments(importItems);
|
||||
|
||||
return CreateCodeDocumentCore(sourceDocument, importSourceDocuments, tagHelpers: null);
|
||||
return CreateCodeDocumentCore(sourceDocument, projectItem.FileKind, importSourceDocuments, tagHelpers: null);
|
||||
}
|
||||
|
||||
internal override RazorCodeDocument CreateCodeDocumentCore(RazorSourceDocument sourceDocument, IReadOnlyList<RazorSourceDocument> importSourceDocuments, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||
internal override RazorCodeDocument CreateCodeDocumentCore(RazorSourceDocument sourceDocument, string fileKind, IReadOnlyList<RazorSourceDocument> importSourceDocuments, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||
{
|
||||
if (sourceDocument == null)
|
||||
{
|
||||
|
|
@ -84,6 +84,11 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
var codeDocument = RazorCodeDocument.Create(sourceDocument, importSourceDocuments, parserOptions, codeGenerationOptions);
|
||||
codeDocument.SetTagHelpers(tagHelpers);
|
||||
|
||||
if (fileKind != null)
|
||||
{
|
||||
codeDocument.SetFileKind(fileKind);
|
||||
}
|
||||
|
||||
return codeDocument;
|
||||
}
|
||||
|
||||
|
|
@ -100,10 +105,10 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
var importItems = importFeature.GetImports(projectItem);
|
||||
var importSourceDocuments = GetImportSourceDocuments(importItems, suppressExceptions: true);
|
||||
|
||||
return CreateCodeDocumentDesignTimeCore(sourceDocument, importSourceDocuments, tagHelpers: null);
|
||||
return CreateCodeDocumentDesignTimeCore(sourceDocument, projectItem.FileKind, importSourceDocuments, tagHelpers: null);
|
||||
}
|
||||
|
||||
internal override RazorCodeDocument CreateCodeDocumentDesignTimeCore(RazorSourceDocument sourceDocument, IReadOnlyList<RazorSourceDocument> importSourceDocuments, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||
internal override RazorCodeDocument CreateCodeDocumentDesignTimeCore(RazorSourceDocument sourceDocument, string fileKind, IReadOnlyList<RazorSourceDocument> importSourceDocuments, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||
{
|
||||
if (sourceDocument == null)
|
||||
{
|
||||
|
|
@ -116,6 +121,11 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
var codeDocument = RazorCodeDocument.Create(sourceDocument, importSourceDocuments, parserOptions, codeGenerationOptions);
|
||||
codeDocument.SetTagHelpers(tagHelpers);
|
||||
|
||||
if (fileKind != null)
|
||||
{
|
||||
codeDocument.SetFileKind(fileKind);
|
||||
}
|
||||
|
||||
return codeDocument;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,12 +34,13 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
|
||||
return directory
|
||||
.EnumerateFiles("*.cshtml", SearchOption.AllDirectories)
|
||||
.Concat(directory.EnumerateFiles("*.razor", SearchOption.AllDirectories))
|
||||
.Select(file =>
|
||||
{
|
||||
var relativePhysicalPath = file.FullName.Substring(absoluteBasePath.Length + 1); // Include leading separator
|
||||
var filePath = "/" + relativePhysicalPath.Replace(Path.DirectorySeparatorChar, '/');
|
||||
|
||||
return new DefaultRazorProjectItem(basePath, filePath, relativePhysicalPath, file);
|
||||
return new DefaultRazorProjectItem(basePath, filePath, relativePhysicalPath, fileKind: null, file);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +58,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
var relativePhysicalPath = file.FullName.Substring(absoluteBasePath.Length + 1); // Include leading separator
|
||||
var filePath = "/" + relativePhysicalPath.Replace(Path.DirectorySeparatorChar, '/');
|
||||
|
||||
return new DefaultRazorProjectItem("/", filePath, relativePhysicalPath, new FileInfo(absolutePath));
|
||||
return new DefaultRazorProjectItem("/", filePath, relativePhysicalPath, fileKind: null, new FileInfo(absolutePath));
|
||||
}
|
||||
|
||||
protected override string NormalizeAndEnsureValidPath(string path)
|
||||
|
|
|
|||
|
|
@ -7,18 +7,22 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
{
|
||||
internal class DefaultRazorProjectItem : RazorProjectItem
|
||||
{
|
||||
private readonly string _fileKind;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="DefaultRazorProjectItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="basePath">The base path.</param>
|
||||
/// <param name="relativePhysicalPath">The physical path of the base path.</param>
|
||||
/// <param name="filePath">The path.</param>
|
||||
/// <param name="fileKind">The file kind. If null, the document kind will be inferred from the file extension.</param>
|
||||
/// <param name="file">The <see cref="FileInfo"/>.</param>
|
||||
public DefaultRazorProjectItem(string basePath, string filePath, string relativePhysicalPath, FileInfo file)
|
||||
public DefaultRazorProjectItem(string basePath, string filePath, string relativePhysicalPath, string fileKind, FileInfo file)
|
||||
{
|
||||
BasePath = basePath;
|
||||
FilePath = filePath;
|
||||
RelativePhysicalPath = relativePhysicalPath;
|
||||
_fileKind = fileKind;
|
||||
File = file;
|
||||
}
|
||||
|
||||
|
|
@ -34,6 +38,8 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
|
||||
public override string RelativePhysicalPath { get; }
|
||||
|
||||
public override string FileKind => _fileKind ?? base.FileKind;
|
||||
|
||||
public override Stream Read() => new FileStream(PhysicalPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||
namespace Microsoft.AspNetCore.Razor.Language
|
||||
{
|
||||
internal static class InputDocumentKind
|
||||
internal static class FileKinds
|
||||
{
|
||||
public static readonly string Component = "component";
|
||||
|
||||
public static readonly string MvcFile = "mvc";
|
||||
public static readonly string Legacy = "mvc";
|
||||
}
|
||||
}
|
||||
|
|
@ -169,24 +169,24 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
document.Items[typeof(RazorCodeGenerationOptions)] = codeGenerationOptions;
|
||||
}
|
||||
|
||||
public static string GetInputDocumentKind(this RazorCodeDocument document)
|
||||
public static string GetFileKind(this RazorCodeDocument document)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
return (string)document.Items[typeof(InputDocumentKind)];
|
||||
return (string)document.Items[typeof(FileKinds)];
|
||||
}
|
||||
|
||||
public static void SetInputDocumentKind(this RazorCodeDocument document, string kind)
|
||||
public static void SetFileKind(this RazorCodeDocument document, string fileKind)
|
||||
{
|
||||
if (document == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(document));
|
||||
}
|
||||
|
||||
document.Items[typeof(InputDocumentKind)] = kind;
|
||||
document.Items[typeof(FileKinds)] = fileKind;
|
||||
}
|
||||
|
||||
private class ImportSyntaxTreesHolder
|
||||
|
|
|
|||
|
|
@ -35,14 +35,14 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
return codeDocument;
|
||||
}
|
||||
|
||||
internal virtual RazorCodeDocument Process(RazorSourceDocument source, IReadOnlyList<RazorSourceDocument> importSources, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||
internal virtual RazorCodeDocument Process(RazorSourceDocument source, string fileKind, IReadOnlyList<RazorSourceDocument> importSources, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
}
|
||||
|
||||
var codeDocument = CreateCodeDocumentCore(source, importSources, tagHelpers);
|
||||
var codeDocument = CreateCodeDocumentCore(source, fileKind, importSources, tagHelpers);
|
||||
ProcessCore(codeDocument);
|
||||
return codeDocument;
|
||||
}
|
||||
|
|
@ -59,30 +59,40 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
return codeDocument;
|
||||
}
|
||||
|
||||
internal virtual RazorCodeDocument ProcessDesignTime(RazorSourceDocument source, IReadOnlyList<RazorSourceDocument> importSources, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||
internal virtual RazorCodeDocument ProcessDesignTime(RazorSourceDocument source, string fileKind, IReadOnlyList<RazorSourceDocument> importSources, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
}
|
||||
|
||||
var codeDocument = CreateCodeDocumentDesignTimeCore(source, importSources, tagHelpers);
|
||||
var codeDocument = CreateCodeDocumentDesignTimeCore(source, fileKind, importSources, tagHelpers);
|
||||
ProcessCore(codeDocument);
|
||||
return codeDocument;
|
||||
}
|
||||
|
||||
protected abstract RazorCodeDocument CreateCodeDocumentCore(RazorProjectItem projectItem);
|
||||
|
||||
internal virtual RazorCodeDocument CreateCodeDocumentCore(RazorSourceDocument source, IReadOnlyList<RazorSourceDocument> importSources, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||
internal virtual RazorCodeDocument CreateCodeDocumentCore(RazorSourceDocument source, string fileKind, IReadOnlyList<RazorSourceDocument> importSources, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||
{
|
||||
return RazorCodeDocument.Create(source, importSources);
|
||||
var codeDocument = RazorCodeDocument.Create(source, importSources);
|
||||
if (fileKind != null)
|
||||
{
|
||||
codeDocument.SetFileKind(fileKind);
|
||||
}
|
||||
return codeDocument;
|
||||
}
|
||||
|
||||
protected abstract RazorCodeDocument CreateCodeDocumentDesignTimeCore(RazorProjectItem projectItem);
|
||||
|
||||
internal virtual RazorCodeDocument CreateCodeDocumentDesignTimeCore(RazorSourceDocument source, IReadOnlyList<RazorSourceDocument> importSources, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||
internal virtual RazorCodeDocument CreateCodeDocumentDesignTimeCore(RazorSourceDocument source, string fileKind, IReadOnlyList<RazorSourceDocument> importSources, IReadOnlyList<TagHelperDescriptor> tagHelpers)
|
||||
{
|
||||
return RazorCodeDocument.Create(source, importSources);
|
||||
var codeDocument = RazorCodeDocument.Create(source, importSources);
|
||||
if (fileKind != null)
|
||||
{
|
||||
codeDocument.SetFileKind(fileKind);
|
||||
}
|
||||
return codeDocument;
|
||||
}
|
||||
|
||||
protected abstract void ProcessCore(RazorCodeDocument codeDocument);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
// 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.Diagnostics;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Razor.Language.Components;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language
|
||||
{
|
||||
|
|
@ -35,6 +38,28 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
/// </summary>
|
||||
public virtual string RelativePhysicalPath => null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the document kind that should be used for the generated document. If possible this will be inferred from the file path. May be null.
|
||||
/// </summary>
|
||||
public virtual string FileKind
|
||||
{
|
||||
get
|
||||
{
|
||||
if (FilePath == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (string.Equals(".razor", Path.GetExtension(FilePath), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return FileKinds.Component;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FileKinds.Legacy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the file contents as readonly <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
Sources = Option("-s", ".cshtml files to compile", CommandOptionType.MultipleValue);
|
||||
Outputs = Option("-o", "Generated output file path", CommandOptionType.MultipleValue);
|
||||
RelativePaths = Option("-r", "Relative path", CommandOptionType.MultipleValue);
|
||||
DocumentKinds = Option("-k", "Document kind", CommandOptionType.MultipleValue);
|
||||
FileKinds = Option("-k", "File kind", CommandOptionType.MultipleValue);
|
||||
ProjectDirectory = Option("-p", "project root directory", CommandOptionType.SingleValue);
|
||||
TagHelperManifest = Option("-t", "tag helper manifest file", CommandOptionType.SingleValue);
|
||||
Version = Option("-v|--version", "Razor language version", CommandOptionType.SingleValue);
|
||||
|
|
@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
|
||||
public CommandOption RelativePaths { get; }
|
||||
|
||||
public CommandOption DocumentKinds { get; }
|
||||
public CommandOption FileKinds { get; }
|
||||
|
||||
public CommandOption ProjectDirectory { get; }
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
var version = RazorLanguageVersion.Parse(Version.Value());
|
||||
var configuration = RazorConfiguration.Create(version, Configuration.Value(), extensions);
|
||||
|
||||
var sourceItems = GetSourceItems(ProjectDirectory.Value(), Sources.Values, Outputs.Values, RelativePaths.Values, DocumentKinds.Values);
|
||||
var sourceItems = GetSourceItems(ProjectDirectory.Value(), Sources.Values, Outputs.Values, RelativePaths.Values, FileKinds.Values);
|
||||
|
||||
var result = ExecuteCore(
|
||||
configuration: configuration,
|
||||
|
|
@ -105,11 +105,11 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
return false;
|
||||
}
|
||||
|
||||
if (DocumentKinds.Values.Count != 0 && DocumentKinds.Values.Count != Sources.Values.Count)
|
||||
if (FileKinds.Values.Count != 0 && FileKinds.Values.Count != Sources.Values.Count)
|
||||
{
|
||||
// 2.x tasks do not specify DocumentKinds - in which case, no values will be present. If a kind for one document is specified, we expect as many kind entries
|
||||
// 2.x tasks do not specify FileKinds - in which case, no values will be present. If a kind for one file is specified, we expect as many kind entries
|
||||
// as sources.
|
||||
Error.WriteLine($"{Sources.Description} has {Sources.Values.Count}, but {DocumentKinds.Description} has {DocumentKinds.Values.Count} values.");
|
||||
Error.WriteLine($"{Sources.Description} has {Sources.Values.Count}, but {FileKinds.Description} has {FileKinds.Values.Count} values.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +171,6 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
var engine = RazorProjectEngine.Create(configuration, compositeFileSystem, b =>
|
||||
{
|
||||
b.Features.Add(new StaticTagHelperFeature() { TagHelpers = tagHelpers, });
|
||||
b.Features.Add(new InputDocumentKindClassifierPass(sourceItems));
|
||||
|
||||
if (GenerateDeclaration.HasValue())
|
||||
{
|
||||
|
|
@ -223,6 +222,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
basePath: "/",
|
||||
filePath: item.FilePath,
|
||||
relativePhysicalPath: item.RelativePhysicalPath,
|
||||
fileKind: item.FileKind,
|
||||
file: new FileInfo(item.SourcePath));
|
||||
|
||||
project.Add(projectItem);
|
||||
|
|
@ -251,15 +251,15 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
}
|
||||
}
|
||||
|
||||
private SourceItem[] GetSourceItems(string projectDirectory, List<string> sources, List<string> outputs, List<string> relativePath, List<string> documentKinds)
|
||||
private SourceItem[] GetSourceItems(string projectDirectory, List<string> sources, List<string> outputs, List<string> relativePath, List<string> fileKinds)
|
||||
{
|
||||
var items = new SourceItem[sources.Count];
|
||||
for (var i = 0; i < items.Length; i++)
|
||||
{
|
||||
var outputPath = Path.Combine(projectDirectory, outputs[i]);
|
||||
var documentKind = documentKinds.Count > 0 ? documentKinds[i] : "mvc";
|
||||
var fileKind = fileKinds.Count > 0 ? fileKinds[i] : "mvc";
|
||||
|
||||
items[i] = new SourceItem(sources[i], outputs[i], relativePath[i], documentKind);
|
||||
items[i] = new SourceItem(sources[i], outputs[i], relativePath[i], fileKind);
|
||||
}
|
||||
|
||||
return items;
|
||||
|
|
@ -297,7 +297,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
|
||||
private readonly struct SourceItem
|
||||
{
|
||||
public SourceItem(string sourcePath, string outputPath, string physicalRelativePath, string documentKind)
|
||||
public SourceItem(string sourcePath, string outputPath, string physicalRelativePath, string fileKind)
|
||||
{
|
||||
SourcePath = sourcePath;
|
||||
OutputPath = outputPath;
|
||||
|
|
@ -305,7 +305,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
FilePath = '/' + physicalRelativePath
|
||||
.Replace(Path.DirectorySeparatorChar, '/')
|
||||
.Replace("//", "/");
|
||||
DocumentKind = documentKind;
|
||||
FileKind = fileKind;
|
||||
}
|
||||
|
||||
public string SourcePath { get; }
|
||||
|
|
@ -316,7 +316,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
|
||||
public string FilePath { get; }
|
||||
|
||||
public string DocumentKind { get; }
|
||||
public string FileKind { get; }
|
||||
}
|
||||
|
||||
private class StaticTagHelperFeature : ITagHelperFeature
|
||||
|
|
@ -342,31 +342,5 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
options.SuppressPrimaryMethodBody = true;
|
||||
}
|
||||
}
|
||||
|
||||
private class InputDocumentKindClassifierPass : RazorEngineFeatureBase, IRazorDocumentClassifierPass
|
||||
{
|
||||
public InputDocumentKindClassifierPass(SourceItem[] sourceItems)
|
||||
{
|
||||
DocumentKinds = new Dictionary<string, string>(sourceItems.Length, StringComparer.OrdinalIgnoreCase);
|
||||
for (var i = 0; i < sourceItems.Length; i++)
|
||||
{
|
||||
var item = sourceItems[i];
|
||||
DocumentKinds[item.SourcePath] = item.DocumentKind;
|
||||
}
|
||||
}
|
||||
|
||||
// Run before other document classifiers
|
||||
public int Order => -1000;
|
||||
|
||||
public Dictionary<string, string> DocumentKinds { get; }
|
||||
|
||||
public void Execute(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
|
||||
{
|
||||
if (DocumentKinds.TryGetValue(codeDocument.Source.FilePath, out var kind))
|
||||
{
|
||||
codeDocument.SetInputDocumentKind(kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,20 +8,26 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
{
|
||||
public class TestRazorProjectItem : RazorProjectItem
|
||||
{
|
||||
private readonly string _fileKind;
|
||||
|
||||
public TestRazorProjectItem(
|
||||
string filePath,
|
||||
string physicalPath = null,
|
||||
string relativePhysicalPath = null,
|
||||
string basePath = "/")
|
||||
string basePath = "/",
|
||||
string fileKind = null)
|
||||
{
|
||||
FilePath = filePath;
|
||||
PhysicalPath = physicalPath;
|
||||
RelativePhysicalPath = relativePhysicalPath;
|
||||
BasePath = basePath;
|
||||
_fileKind = fileKind;
|
||||
}
|
||||
|
||||
public override string BasePath { get; }
|
||||
|
||||
public override string FileKind => _fileKind ?? base.FileKind;
|
||||
|
||||
public override string FilePath { get; }
|
||||
|
||||
public override string PhysicalPath { get; }
|
||||
|
|
|
|||
Loading…
Reference in New Issue