Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Get generated docs from the generator #8678

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,40 @@
to Razor tooling.
-->
<Compile Include="$(MSBuildThisFileDirectory)\src\Shared\LanguageSupport\IsExternalInit.cs" Link="LanguageSupport\IsExternalInit.cs" />

<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.ExternalAccess.Razor\Debug\netstandard2.0\Microsoft.CodeAnalysis.ExternalAccess.Razor.dll" />
<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis\Debug\netstandard2.0\Microsoft.CodeAnalysis.dll" />
<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.Workspaces\Debug\netstandard2.0\Microsoft.CodeAnalysis.Workspaces.dll" />
<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.LanguageServer.Protocol\Debug\netstandard2.0\Microsoft.CodeAnalysis.LanguageServer.Protocol.dll" />
<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CommonLanguageServerProtocol.Framework\Debug\netstandard2.0\Microsoft.CommonLanguageServerProtocol.Framework.dll" />

<!--<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis\Debug\netstandard2.0\Microsoft.CodeAnalysis.dll" />
<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.CSharp\Debug\netstandard2.0\Microsoft.CodeAnalysis.CSharp.dll" />
<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.ExternalAccess.Razor\Debug\netstandard2.0\Microsoft.CodeAnalysis.ExternalAccess.Razor.dll" />
<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.EditorFeatures\Debug\netstandard2.0\Microsoft.CodeAnalysis.EditorFeatures.dll" />-->
<!--<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.EditorFeatures.Common\Debug\netstandard2.0\Microsoft.CodeAnalysis.EditorFeatures.Common.dll" />-->

<!--<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.Workspaces\Debug\netstandard2.0\Microsoft.CodeAnalysis.Workspaces.dll" />
<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.Remote.Workspaces\Debug\netstandard2.0\Microsoft.CodeAnalysis.Remote.Workspaces.dll" />
<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CodeAnalysis.LanguageServer.Protocol\Debug\netstandard2.0\Microsoft.CodeAnalysis.LanguageServer.Protocol.dll" />
<Reference SpecificVersion="true" Include="C:\projects\roslyn\artifacts\bin\Microsoft.CommonLanguageServerProtocol.Framework\Debug\netstandard2.0\Microsoft.CommonLanguageServerProtocol.Framework.dll" />

<Reference SpecificVersion="true" Include="C:\Users\Chris\.nuget\packages\microsoft.visualstudio.languageserver.protocol\17.5.20-preview\lib\netstandard2.0\Microsoft.VisualStudio.LanguageServer.Protocol.dll" />-->

<!--<Reference SpecificVersion="true" Include="C:\Users\Chris\.nuget\packages\system.composition.convention\7.0.0\lib\netstandard2.0\System.Composition.Convention.dll" />
<Reference SpecificVersion="true" Include="C:\Users\Chris\.nuget\packages\system.composition.attributedmodel\7.0.0\lib\netstandard2.0\System.Composition.attributedmodel.dll" />
<Reference SpecificVersion="true" Include="C:\Users\Chris\.nuget\packages\system.composition.typedparts\7.0.0\lib\netstandard2.0\System.Composition.typedparts.dll" />
<Reference SpecificVersion="true" Include="C:\Users\Chris\.nuget\packages\system.composition.runtime\7.0.0\lib\netstandard2.0\System.Composition.Runtime.dll" />
<Reference SpecificVersion="true" Include="C:\Users\Chris\.nuget\packages\system.composition.hosting\7.0.0\lib\netstandard2.0\System.Composition.hosting.dll" />-->

<!--<PackageReference Include="System.Composition" VersionOverride="7.0.0" />-->

<!-- <Reference Include="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.ComponentModel.Composition.dll" Condition="'$(TargetFramework)' == 'net472'" /> -->

</ItemGroup>

<PropertyGroup Label="Package and Assembly Metadata">
<NoWarn>$(NoWarn);MSB3243</NoWarn>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Product>Microsoft ASP.NET Core</Product>
</PropertyGroup>
Expand Down
77 changes: 43 additions & 34 deletions eng/Versions.props

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/Compiler/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="$(MicrosoftCodeAnalysisCommonPackageVersion)" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="$(MicrosoftCodeAnalysisCSharpPackageVersion)" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="$(MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion)" />
<PackageVersion Include="Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler" Version="$(MicrosoftCodeAnalysisExternalAccessRazorCompilerPackageVersion)" />
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="$(MicrosoftCodeAnalysisWorkspacesMSBuildPackageVersion)" />
<PackageVersion Include="Microsoft.CSharp" Version="$(MicrosoftCSharpVersion)" />
<PackageVersion Include="Microsoft.Css.Parser" Version="$(MicrosoftCssParserVersion)" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Description>ASP.NET Core design time hosting infrastructure for the Razor view engine.</Description>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Description>ASP.NET Core design time hosting infrastructure for the Razor view engine.</Description>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Description>ASP.NET Core design time hosting infrastructure for the Razor view engine.</Description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,30 @@ namespace Microsoft.AspNetCore.Razor.Language;
internal sealed class DefaultRazorTagHelperRewritePhase : RazorEnginePhaseBase
{
protected override void ExecuteCore(RazorCodeDocument codeDocument)
{
var context = codeDocument.GetTagHelperContext();
if (context is not null)
{
RewriteTagHelpers(codeDocument, context.Prefix, context.TagHelpers);
}
}

public void RewriteTagHelpers(RazorCodeDocument codeDocument, string prefix, IReadOnlyList<TagHelperDescriptor> tagHelpers)
{
var syntaxTree = codeDocument.GetPreTagHelperSyntaxTree() ?? codeDocument.GetSyntaxTree();
ThrowForMissingDocumentDependency(syntaxTree);

var context = codeDocument.GetTagHelperContext();
if (context?.TagHelpers.Count > 0)
if (tagHelpers.Count > 0)
{
var rewrittenSyntaxTree = TagHelperParseTreeRewriter.Rewrite(syntaxTree, context.Prefix, context.TagHelpers, out var usedHelpers);
var rewrittenSyntaxTree = TagHelperParseTreeRewriter.Rewrite(syntaxTree, prefix, tagHelpers, out var usedHelpers, out var rewrittenMap);
codeDocument.SetSyntaxTree(rewrittenSyntaxTree);
codeDocument.SetReferencedTagHelpers(usedHelpers);
codeDocument.SetRewrittenTagHelpers(rewrittenMap);
}
else
{
codeDocument.SetReferencedTagHelpers(new HashSet<TagHelperDescriptor>());
codeDocument.SetRewrittenTagHelpers(new Dictionary<Syntax.MarkupStartTagSyntax, TagHelperBinding>());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy;

internal static class TagHelperParseTreeRewriter
{
public static RazorSyntaxTree Rewrite(RazorSyntaxTree syntaxTree, string tagHelperPrefix, IEnumerable<TagHelperDescriptor> descriptors, out ISet<TagHelperDescriptor> usedDescriptors)
public static RazorSyntaxTree Rewrite(RazorSyntaxTree syntaxTree, string tagHelperPrefix, IEnumerable<TagHelperDescriptor> descriptors, out ISet<TagHelperDescriptor> usedDescriptors, out Dictionary<MarkupStartTagSyntax, TagHelperBinding> rewrittenMap)
{
var errorSink = new ErrorSink();

Expand All @@ -34,6 +34,7 @@ public static RazorSyntaxTree Rewrite(RazorSyntaxTree syntaxTree, string tagHelp
var diagnostics = CombineErrors(syntaxTree.Diagnostics, errorList).OrderBy(error => error.Span.AbsoluteIndex);

usedDescriptors = rewriter.UsedDescriptors;
rewrittenMap = rewriter.Rewritten;

var newSyntaxTree = RazorSyntaxTree.Create(rewritten, syntaxTree.Source, diagnostics, syntaxTree.Options);
return newSyntaxTree;
Expand Down Expand Up @@ -65,6 +66,10 @@ internal sealed class Rewriter : SyntaxRewriter
private readonly RazorParserFeatureFlags _featureFlags;
private readonly HashSet<TagHelperDescriptor> _usedDescriptors;

// PROTOTYPE:
private readonly Dictionary<MarkupStartTagSyntax, TagHelperBinding> _rewritten;


public Rewriter(
RazorSourceDocument source,
string tagHelperPrefix,
Expand All @@ -80,9 +85,12 @@ public Rewriter(
_htmlAttributeTracker = new List<KeyValuePair<string, string>>();
_featureFlags = featureFlags;
_usedDescriptors = new HashSet<TagHelperDescriptor>();
_rewritten = new Dictionary<MarkupStartTagSyntax, TagHelperBinding>();
_errorSink = errorSink;
}
public HashSet<TagHelperDescriptor> UsedDescriptors => _usedDescriptors;
public Dictionary<MarkupStartTagSyntax, TagHelperBinding> Rewritten => _rewritten;


private TagTracker CurrentTracker => _trackerStack.Count > 0 ? _trackerStack.Peek() : null;

Expand Down Expand Up @@ -286,6 +294,8 @@ private bool TryRewriteTagHelperStart(
// We're in a start TagHelper block.
ValidateStartTagSyntax(tagName, startTag);

_rewritten.Add(startTag, tagHelperBinding);

var rewrittenStartTag = TagHelperBlockRewriter.Rewrite(
tagName,
_featureFlags,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public static class RazorCodeDocumentExtensions
private static readonly char[] NamespaceSeparators = new char[] { '.' };
private static readonly object CssScopeKey = new object();
private static readonly object NamespaceKey = new object();
private static readonly object NoNamespaceToken = new object();

public static TagHelperDocumentContext GetTagHelperContext(this RazorCodeDocument document)
{
Expand Down Expand Up @@ -80,6 +81,26 @@ internal static void SetReferencedTagHelpers(this RazorCodeDocument document, IS
document.Items[nameof(GetReferencedTagHelpers)] = tagHelpers;
}

internal static Dictionary<MarkupStartTagSyntax, TagHelperBinding> GetRewrittenTagHelpers(this RazorCodeDocument document)
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

return document.Items[nameof(GetRewrittenTagHelpers)] as Dictionary<MarkupStartTagSyntax, TagHelperBinding>;
}

internal static void SetRewrittenTagHelpers(this RazorCodeDocument document, Dictionary<MarkupStartTagSyntax, TagHelperBinding> tagHelpers)
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

document.Items[nameof(SetRewrittenTagHelpers)] = tagHelpers;
}

public static RazorSyntaxTree GetPreTagHelperSyntaxTree(this RazorCodeDocument document)
{
if (document == null)
Expand Down Expand Up @@ -160,6 +181,16 @@ public static void SetDocumentIntermediateNode(this RazorCodeDocument document,
document.Items[typeof(DocumentIntermediateNode)] = documentNode;
}

internal static void SetHtmlDocument(this RazorCodeDocument document, RazorHtmlDocument htmlDocument)
{
if (htmlDocument == null)
{
throw new ArgumentNullException(nameof(htmlDocument));
}

document.Items[typeof(RazorHtmlDocument)] = htmlDocument;
}

internal static RazorHtmlDocument GetHtmlDocument(this RazorCodeDocument document)
{
if (document == null)
Expand Down Expand Up @@ -281,18 +312,38 @@ public static void SetCssScope(this RazorCodeDocument document, string cssScope)
document.Items[CssScopeKey] = cssScope;
}

internal static void SetNamespace(this RazorCodeDocument document, string @namespace)
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

document.Items[NamespaceKey] = @namespace;
}

// In general documents will have a relative path (relative to the project root).
// We can only really compute a nice namespace when we know a relative path.
//
// However all kinds of thing are possible in tools. We shouldn't barf here if the document isn't
// set up correctly.
public static bool TryComputeNamespace(this RazorCodeDocument document, bool fallbackToRootNamespace, out string @namespace)
=> TryComputeNamespace(document, fallbackToRootNamespace, check: true, out @namespace);

internal static bool TryComputeNamespace(this RazorCodeDocument document, bool fallbackToRootNamespace, bool check, out string @namespace)
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

var namespaceValue = document.Items[NamespaceKey];
if (namespaceValue == NoNamespaceToken)
{
@namespace = null;
return false;
}

@namespace = (string)document.Items[NamespaceKey];
if (@namespace is null)
{
Expand All @@ -302,11 +353,14 @@ public static bool TryComputeNamespace(this RazorCodeDocument document, bool fal
}

#if DEBUG
// In debug mode, even if we're cached, lets take the hit to run this again and make sure the cached value is correct.
// This is to help us find issues with caching logic during development.
var validateResult = TryComputeNamespaceCore(document, fallbackToRootNamespace, out var validateNamespace);
Debug.Assert(validateResult, "We couldn't compute the namespace, but have a cached value, so something has gone wrong");
Debug.Assert(validateNamespace == @namespace, $"We cached a namespace of {@namespace} but calculated that it should be {validateNamespace}");
if (check)
{
// In debug mode, even if we're cached, lets take the hit to run this again and make sure the cached value is correct.
// This is to help us find issues with caching logic during development.
var validateResult = TryComputeNamespaceCore(document, fallbackToRootNamespace, out var validateNamespace);
Debug.Assert(validateResult, "We couldn't compute the namespace, but have a cached value, so something has gone wrong");
Debug.Assert(validateNamespace == @namespace, $"We cached a namespace of {@namespace} but calculated that it should be {validateNamespace}");
}
#endif

return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#nullable disable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#nullable disable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ internal void EvaluateData(
{
var syntaxTree = ParseDocument(documentContent, featureFlags: featureFlags);

var rewrittenTree = TagHelperParseTreeRewriter.Rewrite(syntaxTree, tagHelperPrefix, descriptors, out _);
var rewrittenTree = TagHelperParseTreeRewriter.Rewrite(syntaxTree, tagHelperPrefix, descriptors, out _, out _);

Assert.Equal(syntaxTree.Root.FullWidth, rewrittenTree.Root.FullWidth);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Description>Razor is a markup syntax for adding server-side logic to web pages. This package contains the Razor design-time infrastructure.</Description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,20 @@
<NoWarn>$(NoWarn);RS2008;RS1036</NoWarn>
<Nullable>enable</Nullable>
<ExcludeFromSourceBuild>false</ExcludeFromSourceBuild>
<DebugType>full</DebugType>

</PropertyGroup>

<ItemGroup>
<Compile Include="..\shared\JsonReaderExtensions.cs" LinkBase="Shared" />
<Compile Include="..\shared\RazorDiagnosticJsonConverter.cs" LinkBase="Shared" />
<Compile Include="..\shared\TagHelperDescriptorJsonConverter.cs" LinkBase="Shared" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
<PackageReference Include="Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler" />
<PackageReference Include="Newtonsoft.Json" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal sealed class RazorSourceGenerationOptions : IEquatable<RazorSourceGener
public LanguageVersion CSharpLanguageVersion { get; set; } = LanguageVersion.CSharp10;

/// <summary>
/// Gets a flag that determines if localized component names should be supported.</c>.
/// Gets a flag that determines if localized component names should be supported.
/// </summary>
public bool SupportLocalizedComponentNames { get; set; } = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,58 @@ private static SourceGeneratorProjectEngine GetGenerationProjectEngine(

return new SourceGeneratorProjectEngine(projectEngine);
}
}

private static RazorProjectEngine GetDesignTimeProjectEngine(
IReadOnlyList<TagHelperDescriptor> tagHelpers,
SourceGeneratorProjectItem item,
IEnumerable<SourceGeneratorProjectItem> imports,
RazorSourceGenerationOptions razorSourceGeneratorOptions)
{
var fileSystem = new VirtualRazorProjectFileSystem();
fileSystem.Add(item);
foreach (var import in imports)
{
fileSystem.Add(import);
}

var projectEngine = RazorProjectEngine.Create(razorSourceGeneratorOptions.Configuration, fileSystem, b =>
{
b.Features.Add(new DefaultTypeNameFeature());
b.SetRootNamespace(razorSourceGeneratorOptions.RootNamespace);

b.Features.Add(new ConfigureRazorCodeGenerationOptions(options =>
{
options.SuppressMetadataSourceChecksumAttributes = !razorSourceGeneratorOptions.GenerateMetadataSourceChecksumAttributes;
options.SupportLocalizedComponentNames = razorSourceGeneratorOptions.SupportLocalizedComponentNames;
}));

b.Features.Add(new StaticTagHelperFeature { TagHelpers = tagHelpers });
b.Features.Add(new DefaultTagHelperDescriptorProvider());

CompilerFeatures.Register(b);
RazorExtensions.Register(b);

b.SetCSharpLanguageVersion(razorSourceGeneratorOptions.CSharpLanguageVersion);
});

return projectEngine;
}
}

internal sealed class StaticTagHelperFeature : RazorEngineFeatureBase, ITagHelperFeature
{
public IReadOnlyList<TagHelperDescriptor> TagHelpers { get; set; }

public IReadOnlyList<TagHelperDescriptor> GetDescriptors() => TagHelpers;

public StaticTagHelperFeature()
{
TagHelpers = new List<TagHelperDescriptor>();
}

public StaticTagHelperFeature(IEnumerable<TagHelperDescriptor> tagHelpers)
{
TagHelpers = new List<TagHelperDescriptor>(tagHelpers);
}
}
}
Loading