Skip to content

Commit 37ebca1

Browse files
authored
Merge pull request #400 from Sergio0694/dev/raw-multiline-toggle
Only emit raw multiline string literals when possible
2 parents 5c83ac3 + dab94bd commit 37ebca1

File tree

6 files changed

+81
-21
lines changed

6 files changed

+81
-21
lines changed

src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.CreateBuildHlslSourceMethod.Syntax.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using ComputeSharp.D2D1.__Internals;
22
using ComputeSharp.SourceGeneration.Helpers;
3+
using Microsoft.CodeAnalysis;
34
using Microsoft.CodeAnalysis.CSharp;
45
using Microsoft.CodeAnalysis.CSharp.Syntax;
56
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
@@ -19,9 +20,16 @@ partial class BuildHlslSource
1920
/// </summary>
2021
/// <param name="hlslSource">The input HLSL source.</param>
2122
/// <param name="hierarchyDepth">The depth of the hierarchy for this type (used to calculate the right indentation).</param>
23+
/// <param name="useRawMultiLineStringLiteralExpression">Whether to use a raw multiline string literal expression</param>
2224
/// <returns>The resulting <see cref="MethodDeclarationSyntax"/> instance for the <c>BuildHlslSource</c> method.</returns>
23-
public static MethodDeclarationSyntax GetSyntax(string hlslSource, int hierarchyDepth)
25+
public static MethodDeclarationSyntax GetSyntax(string hlslSource, int hierarchyDepth, bool useRawMultiLineStringLiteralExpression)
2426
{
27+
SyntaxToken hlslSourceLiteralExpression = useRawMultiLineStringLiteralExpression switch
28+
{
29+
true => SyntaxTokenHelper.CreateRawMultilineStringLiteral(hlslSource, hierarchyDepth),
30+
false => Literal(hlslSource)
31+
};
32+
2533
// This code produces a method declaration as follows:
2634
//
2735
// readonly void global::ComputeSharp.D2D1.__Internals.ID2D1Shader.BuildHlslSource(out string hlslSource)
@@ -38,9 +46,7 @@ public static MethodDeclarationSyntax GetSyntax(string hlslSource, int hierarchy
3846
AssignmentExpression(
3947
SyntaxKind.SimpleAssignmentExpression,
4048
IdentifierName("hlslSource"),
41-
LiteralExpression(
42-
SyntaxKind.StringLiteralExpression,
43-
SyntaxTokenHelper.CreateRawMultilineStringLiteral(hlslSource, hierarchyDepth))))));
49+
LiteralExpression(SyntaxKind.StringLiteralExpression, hlslSourceLiteralExpression)))));
4450
}
4551
}
4652
}

src/ComputeSharp.D2D1.SourceGenerators/ID2D1ShaderGenerator.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,18 +208,24 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
208208
context.AddSource($"{item.Info.Hierarchy.FilenameHint}.{nameof(LoadDispatchData)}.g.cs", compilationUnit.GetText(Encoding.UTF8));
209209
});
210210

211-
// Get the BuildHlslSource() info (hierarchy and HLSL source)
212-
IncrementalValuesProvider<(HierarchyInfo Hierarchy, string HlslSource)> hlslSourceInfo =
211+
// Check whether raw multiline string literals can be used (C# 11)
212+
IncrementalValueProvider<bool> canUseRawMultilineStringLiterals =
213+
context.ParseOptionsProvider
214+
.Select((item, _) => item is CSharpParseOptions { LanguageVersion: >= LanguageVersion.CSharp11 });
215+
216+
// Get the BuildHlslSource() info (hierarchy, HLSL source and parsing options)
217+
IncrementalValuesProvider<((HierarchyInfo Hierarchy, string HlslSource) Info, bool CanUseRawMultilineStringLiterals)> hlslSourceInfo =
213218
shaderInfoWithErrors
214-
.Select(static (item, _) => (item.Hierarchy, item.HlslShaderSource.HlslSource));
219+
.Select(static (item, _) => (item.Hierarchy, item.HlslShaderSource.HlslSource))
220+
.Combine(canUseSkipLocalsInit);
215221

216222
// Generate the BuildHlslSource() methods
217223
context.RegisterSourceOutput(hlslSourceInfo, static (context, item) =>
218224
{
219-
MethodDeclarationSyntax buildHlslStringMethod = BuildHlslSource.GetSyntax(item.HlslSource, item.Hierarchy.Hierarchy.Length);
220-
CompilationUnitSyntax compilationUnit = GetCompilationUnitFromMethod(item.Hierarchy, buildHlslStringMethod, canUseSkipLocalsInit: false);
225+
MethodDeclarationSyntax buildHlslStringMethod = BuildHlslSource.GetSyntax(item.Info.HlslSource, item.Info.Hierarchy.Hierarchy.Length, item.CanUseRawMultilineStringLiterals);
226+
CompilationUnitSyntax compilationUnit = GetCompilationUnitFromMethod(item.Info.Hierarchy, buildHlslStringMethod, canUseSkipLocalsInit: false);
221227

222-
context.AddSource($"{item.Hierarchy.FilenameHint}.{nameof(BuildHlslSource)}.g.cs", compilationUnit.GetText(Encoding.UTF8));
228+
context.AddSource($"{item.Info.Hierarchy.FilenameHint}.{nameof(BuildHlslSource)}.g.cs", compilationUnit.GetText(Encoding.UTF8));
223229
});
224230

225231
// Get a filtered sequence to enable caching for the HLSL source info, before the shader compilation step

src/ComputeSharp.SourceGeneration/ComputeSharp.SourceGeneration.projitems

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
</PropertyGroup>
1111
<ItemGroup>
1212
<Compile Include="$(MSBuildThisFileDirectory)Extensions\AttributeDataExtensions.cs" />
13+
<Compile Include="$(MSBuildThisFileDirectory)Extensions\IncrementalValueProviderExtensions.cs" />
1314
<Compile Include="$(MSBuildThisFileDirectory)Extensions\CompilationExtensions.cs" />
1415
<Compile Include="$(MSBuildThisFileDirectory)Extensions\DiagnosticsExtensions.cs" />
1516
<Compile Include="$(MSBuildThisFileDirectory)Extensions\HashCodeExtensions.cs" />
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using Microsoft.CodeAnalysis;
6+
7+
namespace ComputeSharp.SourceGeneration.Extensions;
8+
9+
/// <summary>
10+
/// Extension methods for the <see cref="IncrementalValueProvider{TValue}"/> type.
11+
/// </summary>
12+
internal static class IncrementalValueProviderExtensions
13+
{
14+
/// <summary>
15+
/// Combines three <see cref="IncrementalValueProvider{TValue}"/> instances.
16+
/// </summary>
17+
/// <typeparam name="T1">The type of values produced by the first <see cref="IncrementalValueProvider{TValue}"/> input.</typeparam>
18+
/// <typeparam name="T2">The type of values produced by the second <see cref="IncrementalValueProvider{TValue}"/> input.</typeparam>
19+
/// <typeparam name="T3">The type of values produced by the third <see cref="IncrementalValueProvider{TValue}"/> input.</typeparam>
20+
/// <param name="source1">The first <see cref="IncrementalValueProvider{TValue}"/> input.</param>
21+
/// <param name="source2">The second <see cref="IncrementalValueProvider{TValue}"/> input.</param>
22+
/// <param name="source3">The third <see cref="IncrementalValueProvider{TValue}"/> input.</param>
23+
/// <returns>The resulting combined <see cref="IncrementalValueProvider{TValue}"/> result.</returns>
24+
public static IncrementalValueProvider<(T1, T2, T3)> Combine<T1, T2, T3>(
25+
this IncrementalValueProvider<T1> source1,
26+
IncrementalValueProvider<T2> source2,
27+
IncrementalValueProvider<T3> source3)
28+
{
29+
return
30+
source1
31+
.Combine(source2)
32+
.Combine(source3)
33+
.Select(static (items, _) => (items.Left.Left, items.Left.Right, items.Right));
34+
}
35+
}

src/ComputeSharp.SourceGenerators/IShaderGenerator.CreateBuildHlslSourceMethod.Syntax.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using ComputeSharp.__Internals;
55
using ComputeSharp.SourceGeneration.Helpers;
66
using ComputeSharp.SourceGenerators.Models;
7+
using Microsoft.CodeAnalysis;
78
using Microsoft.CodeAnalysis.CSharp;
89
using Microsoft.CodeAnalysis.CSharp.Syntax;
910
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
@@ -24,12 +25,13 @@ partial class BuildHlslSource
2425
/// <param name="hlslSourceInfo">The input <see cref="HlslShaderSourceInfo"/> instance to use.</param>
2526
/// <param name="supportsDynamicShaders">Indicates whether or not dynamic shaders are supported.</param>
2627
/// <param name="hierarchyDepth">The depth of the hierarchy for this type (used to calculate the right indentation).</param>
28+
/// <param name="useRawMultiLineStringLiteralExpression">Whether to use a raw multiline string literal expression</param>
2729
/// <returns>The resulting <see cref="MethodDeclarationSyntax"/> instance for the <c>BuildHlslSource</c> method.</returns>
28-
public static MethodDeclarationSyntax GetSyntax(HlslShaderSourceInfo hlslSourceInfo, bool supportsDynamicShaders, int hierarchyDepth)
30+
public static MethodDeclarationSyntax GetSyntax(HlslShaderSourceInfo hlslSourceInfo, bool supportsDynamicShaders, int hierarchyDepth, bool useRawMultiLineStringLiteralExpression)
2931
{
3032
// Generate the necessary body statements depending on whether dynamic shaders are supported
3133
ImmutableArray<StatementSyntax> bodyStatements = supportsDynamicShaders
32-
? GenerateRenderMethodBody(hlslSourceInfo, hierarchyDepth)
34+
? GenerateRenderMethodBody(hlslSourceInfo, hierarchyDepth, useRawMultiLineStringLiteralExpression)
3335
: GenerateEmptyMethodBody();
3436

3537
// This code produces a method declaration as follows:
@@ -81,8 +83,9 @@ private static ImmutableArray<StatementSyntax> GenerateEmptyMethodBody()
8183
/// </summary>
8284
/// <param name="hlslSourceInfo">The input <see cref="HlslShaderSourceInfo"/> instance to use.</param>
8385
/// <param name="hierarchyDepth">The depth of the hierarchy for this type (used to calculate the right indentation).</param>
86+
/// <param name="useRawMultiLineStringLiteralExpression">Whether to use a raw multiline string literal expression</param>
8487
/// <returns>The series of statements to build the HLSL source to compile to execute the current shader.</returns>
85-
private static ImmutableArray<StatementSyntax> GenerateRenderMethodBody(HlslShaderSourceInfo hlslSourceInfo, int hierarchyDepth)
88+
private static ImmutableArray<StatementSyntax> GenerateRenderMethodBody(HlslShaderSourceInfo hlslSourceInfo, int hierarchyDepth, bool useRawMultiLineStringLiteralExpression)
8689
{
8790
using ImmutableArrayBuilder<StatementSyntax> statements = ImmutableArrayBuilder<StatementSyntax>.Rent();
8891

@@ -112,19 +115,23 @@ void FlushText()
112115
{
113116
if (textBuilder.Length > 0)
114117
{
115-
string text = textBuilder.ToString();
118+
string hlslSource = textBuilder.ToString();
116119

117-
textBuilder.Append(text);
120+
textBuilder.Append(hlslSource);
118121

119122
sizeHint += textBuilder.Length;
120123

124+
SyntaxToken hlslSourceLiteralExpression = useRawMultiLineStringLiteralExpression switch
125+
{
126+
true => SyntaxTokenHelper.CreateRawMultilineStringLiteral(hlslSource, hierarchyDepth),
127+
false => Literal(hlslSource)
128+
};
129+
121130
statements.Add(
122131
ExpressionStatement(
123132
InvocationExpression(
124133
MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName("builder"), IdentifierName("Append")))
125-
.AddArgumentListArguments(Argument(LiteralExpression(
126-
SyntaxKind.StringLiteralExpression,
127-
SyntaxTokenHelper.CreateRawMultilineStringLiteral(text, hierarchyDepth))))));
134+
.AddArgumentListArguments(Argument(LiteralExpression(SyntaxKind.StringLiteralExpression, hlslSourceLiteralExpression)))));
128135

129136
textBuilder.Clear();
130137
}

src/ComputeSharp.SourceGenerators/IShaderGenerator.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,21 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
154154
context.AddSource($"{item.Info.Hierarchy.FilenameHint}.{nameof(LoadDispatchData)}.g.cs", compilationUnit.GetText(Encoding.UTF8));
155155
});
156156

157+
// Check whether raw multiline string literals can be used (C# 11)
158+
IncrementalValueProvider<bool> canUseRawMultilineStringLiterals =
159+
context.ParseOptionsProvider
160+
.Select((item, _) => item is CSharpParseOptions { LanguageVersion: >= LanguageVersion.CSharp11 });
161+
157162
// Get the BuildHlslSource info (hierarchy, HLSL source and parsing options)
158-
IncrementalValuesProvider<((HierarchyInfo Hierarchy, HlslShaderSourceInfo HlslShaderSource) Info, (bool CanUseSkipLocalsInit, bool SupportsDynamicShaders) Options)> hlslSourceInfo =
163+
IncrementalValuesProvider<((HierarchyInfo Hierarchy, HlslShaderSourceInfo HlslShaderSource) Info, (bool CanUseSkipLocalsInit, bool SupportsDynamicShaders, bool CanUseRawMultilineStringLiterals) Options)> hlslSourceInfo =
159164
shaderInfoWithErrors
160165
.Select(static (item, _) => (item.Hierarchy, item.HlslShaderSource))
161-
.Combine(canUseSkipLocalsInit.Combine(supportsDynamicShaders));
166+
.Combine(canUseSkipLocalsInit.Combine(supportsDynamicShaders, canUseRawMultilineStringLiterals));
162167

163168
// Generate the BuildHlslSource() methods
164169
context.RegisterSourceOutput(hlslSourceInfo, static (context, item) =>
165170
{
166-
MethodDeclarationSyntax buildHlslStringMethod = BuildHlslSource.GetSyntax(item.Info.HlslShaderSource, item.Options.SupportsDynamicShaders, item.Info.Hierarchy.Hierarchy.Length);
171+
MethodDeclarationSyntax buildHlslStringMethod = BuildHlslSource.GetSyntax(item.Info.HlslShaderSource, item.Options.SupportsDynamicShaders, item.Info.Hierarchy.Hierarchy.Length, item.Options.CanUseRawMultilineStringLiterals);
167172
CompilationUnitSyntax compilationUnit = GetCompilationUnitFromMethod(item.Info.Hierarchy, buildHlslStringMethod, item.Options.CanUseSkipLocalsInit);
168173

169174
context.AddSource($"{item.Info.Hierarchy.FilenameHint}.{nameof(BuildHlslSource)}.g.cs", compilationUnit.GetText(Encoding.UTF8));

0 commit comments

Comments
 (0)