Skip to content

Commit b8286f3

Browse files
author
machibuse
committed
Fix typos in method names within PropertyVisitor and enhance nullable string property handling. Update README with detailed usage instructions. Adjust IntelliJ VCS configuration.
1 parent 4ec5917 commit b8286f3

3 files changed

Lines changed: 151 additions & 14 deletions

File tree

README.md

Lines changed: 137 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,138 @@
1-
# A Roslyn PostProcessor for protoc generated files to add Guid support
1+
# Porticle.Grpc.GuidMapper
22

3-
This library allows you to map string and StringValue to Guid and Guid?.
3+
A Roslyn-based post-processor for protoc-generated files that adds native Guid, Guid? and string? types in gRPC services.
4+
5+
## Overview
6+
7+
This library allows you to automatically convert PROTO string or StringValue fields to C# Guid, Guid? or string? types in protoc-generated files, enabling seamless integration of
8+
GUIDs in your gRPC services without manual conversion
9+
code.
10+
11+
## Installation
12+
13+
### Install the package via NuGet:
14+
```powershell
15+
dotnet add package Porticle.Grpc.GuidMapper
16+
```
17+
18+
After installing the Package, this Post build step ist dynamically added to your build.
19+
20+
```msbuild
21+
<Project>
22+
<Target Name="RunProtoPostProcessing" AfterTargets="Protobuf_Compile">
23+
<ItemGroup>
24+
<_FilesToPostProcess Include="$(MSBuildProjectDirectory)\%(Protobuf_Compile.OutputDir)\%(Protobuf_Compile.Filename)" />
25+
</ItemGroup>
26+
<Message Text="Proto Postprocessing" Importance="high" />
27+
<Exec Command="dotnet &quot;$(MSBuildThisFileDirectory)..\tools\$(TargetFramework)\Porticle.Grpc.GuidMapper.dll&quot; -- %(_FilesToPostProcess.Identity)" Condition="'@(_FilesToPostProcess)' != ''" />
28+
</Target>
29+
</Project>
30+
```
31+
32+
Dont wonder ist you cant se it in your csproj file. It is dynamically added when your build is processed.
33+
34+
## Usage
35+
36+
There are three things you can do in your .proto files:
37+
- Add `// [GrpcGuid]` as comment to a string field - Converts the corresponding c# string property to Guid
38+
- Add `// [GrpcGuid]` as comment to a StringValue field - Converts the corresponding c# string property to Guid?
39+
- Add `// [NullableString]` as comment to a StringValue field - Converts the corresponding c# string property to string?
40+
41+
42+
First an Example of a default .proto file
43+
44+
### Without GuidMapper
45+
```protobuf
46+
syntax = "proto3";
47+
48+
import "google/protobuf/wrappers.proto";
49+
50+
message User {
51+
// Guid of the user object
52+
string id = 1;
53+
54+
// Optional reference ID
55+
google.protobuf.StringValue optional_reference_id = 4;
56+
57+
// Name
58+
string name = 2;
59+
60+
// Optional description
61+
google.protobuf.StringValue description = 3;
62+
}
63+
```
64+
Will result in generated code like this
65+
```csharp
66+
/// <summary>Guid of the user object</summary>
67+
public string Id {
68+
get { return id_; }
69+
set { id_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); }
70+
}
71+
72+
/// <summary>Optional reference ID</summary>
73+
public string OptionalReferenceId {
74+
get { return optionalReferenceId_; }
75+
set { optionalReferenceId_ = value; }
76+
}
77+
78+
/// <summary>Name</summary>
79+
public string Name {
80+
get { return name_; }
81+
set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); }
82+
}
83+
84+
/// <summary>Optional description</summary>
85+
public string Description {
86+
get { return description_; }
87+
set { description_ = value; }
88+
}
89+
```
90+
91+
### With GuidMapper
92+
```protobuf
93+
syntax = "proto3";
94+
95+
import "google/protobuf/wrappers.proto";
96+
97+
message User {
98+
// [GrpcGuid] Guid of the user object
99+
string id = 1;
100+
101+
// [GrpcGuid] Optional reference ID
102+
google.protobuf.StringValue optional_reference_id = 4;
103+
104+
// Name
105+
string name = 2;
106+
107+
// [NullableString] Optional description
108+
google.protobuf.StringValue description = 3;
109+
}
110+
```
111+
Will result in generated code like this
112+
```csharp
113+
/// <summary>[GrpcGuid] Guid of the user object</summary>
114+
public global::System.Guid Id {
115+
get {return global::System.Guid.Parse(id_); }
116+
set { id_ = (value).ToString("D"); }
117+
}
118+
119+
/// <summary>[GrpcGuid] Optional reference ID</summary>
120+
public global::System.Guid? OptionalReferenceId {
121+
get {if(optionalReferenceId_==null)return default; return global::System.Guid.Parse(optionalReferenceId_); }
122+
set { optionalReferenceId_ = (value)?.ToString("D"); }
123+
}
124+
125+
/// <summary>Name</summary>
126+
public string Name {
127+
get { return name_; }
128+
set { name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); }
129+
}
130+
131+
#nullable enable
132+
/// <summary>[NullableString] Optional description</summary>
133+
public string? Description {
134+
get { return description_; }
135+
set { description_ = value; }
136+
}
137+
#nullable disable
138+
```

Source/.idea/.idea.Porticle.Grpc/.idea/vcs.xml

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

Source/Porticle.Grpc.GuidMapper/PropertyVisitor.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,18 @@ public class PropertyVisitor : CSharpSyntaxRewriter
4141

4242
if (property.GetLeadingTrivia().ToFullString().Contains("[GrpcGuid]"))
4343
{
44-
return ConcertToGuidProperty(property);
44+
return ConvertToGuidProperty(property);
4545
}
4646

4747
if (property.GetLeadingTrivia().ToFullString().Contains("[NullableString]"))
4848
{
49-
return ConcertToNullableStringProperty(property);
49+
return ConvertToNullableStringProperty(property);
5050
}
5151

5252
return null;
5353
}
5454

55-
private PropertyDeclarationSyntax? ConcertToNullableStringProperty(PropertyDeclarationSyntax property)
55+
private PropertyDeclarationSyntax? ConvertToNullableStringProperty(PropertyDeclarationSyntax property)
5656
{
5757
var setter = property.AccessorList?.Accessors.FirstOrDefault(a => a.IsKind(SyntaxKind.SetAccessorDeclaration));
5858

@@ -70,11 +70,19 @@ public class PropertyVisitor : CSharpSyntaxRewriter
7070
return null;
7171
}
7272

73-
// Change property type to string?
74-
return property.WithType(SyntaxFactory.ParseTypeName("global::System.String?").WithTrailingTrivia(SyntaxFactory.Space));
73+
var enableDirective = SyntaxFactory.Trivia(SyntaxFactory.NullableDirectiveTrivia(SyntaxFactory.Token(SyntaxKind.EnableKeyword), true));
74+
var disableDirective = SyntaxFactory.Trivia(SyntaxFactory.NullableDirectiveTrivia(SyntaxFactory.Token(SyntaxKind.DisableKeyword), true));
75+
76+
var leadingTrivia = SyntaxFactory.TriviaList(enableDirective, SyntaxFactory.ElasticCarriageReturnLineFeed);
77+
var trailingTrivia = SyntaxFactory.TriviaList(SyntaxFactory.ElasticCarriageReturnLineFeed, disableDirective);
78+
79+
return property
80+
.WithType(SyntaxFactory.ParseTypeName("string?").WithTrailingTrivia(SyntaxFactory.ElasticSpace))
81+
.WithLeadingTrivia(leadingTrivia.AddRange(property.GetLeadingTrivia()))
82+
.WithTrailingTrivia(property.GetTrailingTrivia().AddRange(trailingTrivia));
7583
}
7684

77-
private PropertyDeclarationSyntax? ConcertToGuidProperty(PropertyDeclarationSyntax property)
85+
private PropertyDeclarationSyntax? ConvertToGuidProperty(PropertyDeclarationSyntax property)
7886
{
7987
var setter = property.AccessorList?.Accessors.FirstOrDefault(a => a.IsKind(SyntaxKind.SetAccessorDeclaration));
8088

0 commit comments

Comments
 (0)