Skip to content

Commit 1d8006c

Browse files
author
machibuse
committed
Refactor TypeMapper to utilize MSBuild task for post-processing, replace console-based logging with TaskLoggingHelper
1 parent 7a078a4 commit 1d8006c

File tree

7 files changed

+96
-62
lines changed

7 files changed

+96
-62
lines changed

Source/Porticle.Grpc.TypeMapper/ClassVisitor.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
using Microsoft.CodeAnalysis;
1+
using Microsoft.Build.Utilities;
2+
using Microsoft.CodeAnalysis;
23
using Microsoft.CodeAnalysis.CSharp;
34
using Microsoft.CodeAnalysis.CSharp.Syntax;
45

56
namespace Porticle.Grpc.TypeMapper;
67

7-
public class ClassVisitor : CSharpSyntaxRewriter
8+
public class ClassVisitor(TaskLoggingHelper log) : CSharpSyntaxRewriter
89
{
910
public override SyntaxNode? VisitClassDeclaration(ClassDeclarationSyntax node)
1011
{
@@ -18,7 +19,7 @@ public class ClassVisitor : CSharpSyntaxRewriter
1819
var trivia = node.GetLeadingTrivia().Add(SyntaxFactory.Comment("/// <remark>" + marker + "</remark>")).Add(SyntaxFactory.CarriageReturnLineFeed);
1920
node = node.WithLeadingTrivia(trivia);
2021

21-
var propertyVisitor = new PropertyVisitor();
22+
var propertyVisitor = new PropertyVisitor(log);
2223
node = (ClassDeclarationSyntax)propertyVisitor.Visit(node);
2324

2425
if (propertyVisitor.NeedGuidConverter) node = node.AddMembers(ClassFromSource(ListWrappers.RepeatedFieldGuidWrapper));

Source/Porticle.Grpc.TypeMapper/Porticle.Grpc.TypeMapper.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<OutputType>Exe</OutputType>
43
<ImplicitUsings>enable</ImplicitUsings>
54
<Nullable>enable</Nullable>
65
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
@@ -20,13 +19,16 @@
2019
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
2120
<TargetFrameworks>net9.0;net8.0</TargetFrameworks>
2221
<PackageReadmeFile>readme.md</PackageReadmeFile>
22+
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
2323
</PropertyGroup>
2424
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
2525
<WarningsAsErrors>NU1605</WarningsAsErrors>
2626
<NoWarn>1701;1702;NU5119</NoWarn>
2727
</PropertyGroup>
2828

2929
<ItemGroup>
30+
<PackageReference Include="JetBrains.Annotations" Version="2025.2.0"/>
31+
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="17.14.8"/>
3032
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0"/>
3133
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.14.0"/>
3234
</ItemGroup>
Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
<Project>
2+
<!-- Importiere den Task aus der DLL im NuGet-Paket -->
3+
<UsingTask
4+
TaskName="Porticle.Grpc.ProtoPostProcessor"
5+
AssemblyFile="$(MSBuildThisFileDirectory)../tools/$(TargetFramework)/Porticle.Grpc.TypeMapper.dll"/>
6+
27
<Target Name="RunProtoPostProcessing" AfterTargets="Protobuf_Compile">
38
<ItemGroup>
49
<_FilesToPostProcess Include="$(MSBuildProjectDirectory)/%(Protobuf_Compile.OutputDir)/%(Protobuf_Compile.Filename)"/>
510
</ItemGroup>
6-
<Message Text="Proto Postprocessing" Importance="high"/>
7-
<Exec Command="dotnet &quot;$(MSBuildThisFileDirectory)../tools/$(TargetFramework)/Porticle.Grpc.TypeMapper.dll&quot; -- %(_FilesToPostProcess.Identity)" Condition="'@(_FilesToPostProcess)' != ''"/>
11+
<ProtoPostProcessor
12+
FilesToPostProcess="@(_FilesToPostProcess)"
13+
WrapAllNonNullableStrings="$(PorticleGrpcTypeMapper_WrapAllNonNullableStrings)"
14+
WrapAllNullableStringValues="$(PorticleGrpcTypeMapper_WrapAllNullableStringValues)"
15+
Condition="'@(_FilesToPostProcess)' != ''"/>
816
</Target>
917
</Project>

Source/Porticle.Grpc.TypeMapper/Program.cs

Lines changed: 0 additions & 42 deletions
This file was deleted.

Source/Porticle.Grpc.TypeMapper/PropertyVisitor.cs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
using Microsoft.CodeAnalysis;
1+
using Microsoft.Build.Utilities;
2+
using Microsoft.CodeAnalysis;
23
using Microsoft.CodeAnalysis.CSharp;
34
using Microsoft.CodeAnalysis.CSharp.Syntax;
45

56
namespace Porticle.Grpc.TypeMapper;
67

7-
public class PropertyVisitor : CSharpSyntaxRewriter
8+
public class PropertyVisitor(TaskLoggingHelper log) : CSharpSyntaxRewriter
89
{
910
public HashSet<PropertyToField> ReplaceProps = new();
1011

@@ -36,15 +37,15 @@ public class PropertyVisitor : CSharpSyntaxRewriter
3637

3738
if (getter?.Body == null)
3839
{
39-
Console.WriteLine($"[Error] No getter found in property {property.Identifier}");
40+
log.LogError($"[Error] No getter found in property {property.Identifier}");
4041
return null;
4142
}
4243

4344
var returnStatement = getter.Body?.Statements.OfType<ReturnStatementSyntax>().FirstOrDefault();
4445

4546
if (returnStatement?.Expression == null)
4647
{
47-
Console.WriteLine($"[Error] Getter has no valid return statement in property {property.Identifier}");
48+
log.LogError($"Getter has no valid return statement in property {property.Identifier}");
4849
return null;
4950
}
5051

@@ -67,7 +68,7 @@ public class PropertyVisitor : CSharpSyntaxRewriter
6768
{
6869
if (isNullable)
6970
{
70-
Console.WriteLine("[Error] Nullable Guid is not supported for repeated fields because protoc don't allow null for lists");
71+
log.LogError("Nullable Guid is not supported for repeated fields because protoc don't allow null for lists");
7172
}
7273
else
7374
{
@@ -85,7 +86,7 @@ public class PropertyVisitor : CSharpSyntaxRewriter
8586

8687
if (property.GetLeadingTrivia().ToFullString().Contains("[NullableString]"))
8788
if (isNullable)
88-
Console.WriteLine("[Error] Nullable string is not supported for repeated fields because protoc don't allow null for lists");
89+
log.LogError("Nullable string is not supported for repeated fields because protoc don't allow null for lists");
8990

9091
return null;
9192
}
@@ -185,15 +186,15 @@ public class PropertyVisitor : CSharpSyntaxRewriter
185186

186187
if (setter?.Body == null)
187188
{
188-
Console.WriteLine($"[Error] No setter found in property {property.Identifier}");
189+
log.LogError($"No setter found in property {property.Identifier}");
189190
return null;
190191
}
191192

192193
var isNullable = !setter.Body.ToFullString().Contains("ProtoPreconditions.CheckNotNull");
193194

194195
if (!isNullable)
195196
{
196-
Console.WriteLine($"[Error] String property {property.Identifier} ist not nullable");
197+
log.LogError($"String property {property.Identifier} ist not nullable");
197198
return null;
198199
}
199200

@@ -217,7 +218,7 @@ public class PropertyVisitor : CSharpSyntaxRewriter
217218

218219
if (setter.Body == null)
219220
{
220-
Console.WriteLine($"[Error] No setter found in property {property.Identifier}");
221+
log.LogError($"No setter found in property {property.Identifier}");
221222
return null;
222223
}
223224

@@ -256,23 +257,23 @@ public class PropertyVisitor : CSharpSyntaxRewriter
256257

257258
if (getter?.Body == null)
258259
{
259-
Console.WriteLine($"[Error] No getter found in property {property.Identifier}");
260+
log.LogError($"No getter found in property {property.Identifier}");
260261
return null;
261262
}
262263

263264
var returnStatement = getter.Body?.Statements.OfType<ReturnStatementSyntax>().FirstOrDefault();
264265

265266
if (returnStatement?.Expression == null)
266267
{
267-
Console.WriteLine($"[Error] Getter has no valid return statement in property {property.Identifier}");
268+
log.LogError($"Getter has no valid return statement in property {property.Identifier}");
268269
return null;
269270
}
270271

271272
var originalReturnExpression = returnStatement.Expression;
272273

273274
if (originalReturnExpression is not IdentifierNameSyntax identifierNameSyntax)
274275
{
275-
Console.WriteLine($"[Error] Getter return statement should be a simple identifier in property {property.Identifier}");
276+
log.LogError($"Getter return statement should be a simple identifier in property {property.Identifier}");
276277
return null;
277278
}
278279

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using JetBrains.Annotations;
2+
using Microsoft.Build.Framework;
3+
using Microsoft.CodeAnalysis.CSharp;
4+
using Task = Microsoft.Build.Utilities.Task;
5+
6+
namespace Porticle.Grpc.TypeMapper;
7+
8+
/// <inheritdoc />
9+
[UsedImplicitly]
10+
public class ProtoPostProcessor : Task
11+
{
12+
[Required] public ITaskItem[] FilesToPostProcess { get; set; }
13+
14+
public bool WrapAllNonNullableStrings { get; set; }
15+
public bool WrapAllNullableStringValues { get; set; }
16+
17+
public override bool Execute()
18+
{
19+
Log.LogMessage(MessageImportance.High,
20+
$"ProtoPostProcessor: WrapAllNonNullableStrings:{WrapAllNonNullableStrings} WrapAllNullableStringValues:{WrapAllNullableStringValues} FileCount:{FilesToPostProcess.Length}");
21+
foreach (var item in FilesToPostProcess)
22+
{
23+
var file = item.ItemSpec;
24+
Log.LogMessage(MessageImportance.High, $"Verarbeite: {file}");
25+
26+
var basename = Path.GetFileNameWithoutExtension(file);
27+
28+
if (string.IsNullOrWhiteSpace(basename))
29+
{
30+
Log.LogError("Nothing to preprocess - no filename given");
31+
return false;
32+
}
33+
34+
var directory = Path.GetDirectoryName(file)!;
35+
36+
string[] filenames = [StringUtils.LowerUnderscoreToUpperCamelProtocWay(basename) + ".cs", StringUtils.LowerUnderscoreToUpperCamelGrpcWay(basename) + "Grpc.cs"];
37+
38+
foreach (var filename in filenames)
39+
{
40+
var filePath = Path.Combine(directory, filename);
41+
42+
var originalCode = File.ReadAllText(filePath);
43+
var tree = CSharpSyntaxTree.ParseText(originalCode);
44+
var root = tree.GetRoot();
45+
File.WriteAllText(filePath + "_", root.ToFullString());
46+
47+
var classVisitor = new ClassVisitor(Log);
48+
root = classVisitor.Visit(root);
49+
50+
File.WriteAllText(filePath, root.ToFullString());
51+
Log.LogMessage(MessageImportance.High, "Grpc-Post-processing complete.");
52+
}
53+
}
54+
55+
// return false, when errors was logged
56+
return !Log.HasLoggedErrors;
57+
}
58+
}

Source/Porticle.Grpc.UnitTests/Porticle.Grpc.UnitTests.csproj

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,17 @@
3030
<ProjectReference Include="..\Porticle.Grpc.TypeMapper\Porticle.Grpc.TypeMapper.csproj"/>
3131
</ItemGroup>
3232

33+
<UsingTask TaskName="Porticle.Grpc.TypeMapper.ProtoPostProcessor"
34+
AssemblyFile="$(MSBuildProjectDirectory)\..\Porticle.Grpc.TypeMapper\bin\$(Configuration)\$(TargetFramework)\Porticle.Grpc.TypeMapper.dll"/>
35+
3336
<Target Name="RunProtoPostProcessing" AfterTargets="Protobuf_Compile">
3437
<ItemGroup>
3538
<_FilesToPostProcess Include="$(MSBuildProjectDirectory)\%(Protobuf_Compile.OutputDir)\%(Protobuf_Compile.Filename)"/>
3639
</ItemGroup>
37-
<Message Text="Proto Postprocessing" Importance="high"/>
38-
<Exec Command="dotnet &quot;$(MSBuildProjectDirectory)/../Porticle.Grpc.TypeMapper/bin/$(Configuration)/$(TargetFramework)/Porticle.Grpc.TypeMapper.dll&quot; -- %(_FilesToPostProcess.Identity)" Condition="'@(_FilesToPostProcess)' != ''"/>
40+
<ProtoPostProcessor
41+
FilesToPostProcess="@(_FilesToPostProcess)"
42+
WrapAllNonNullableStrings="$(PorticleGrpcTypeMapper_WrapAllNonNullableStrings)"
43+
WrapAllNullableStringValues="$(PorticleGrpcTypeMapper_WrapAllNullableStringValues)"
44+
Condition="'@(_FilesToPostProcess)' != ''"/>
3945
</Target>
4046
</Project>

0 commit comments

Comments
 (0)