Skip to content

Commit 6143d42

Browse files
author
machibuse
committed
Add ICustomDiagnosticMessage to message classes and streamline ListWrappers implementation
- Implement `ToDiagnosticString` method in message classes for custom diagnostics. - Use regex for post-processing base type additions in `ProtoPostProcessor` to handle preprocessor directives. - Simplify `ListWrappers` by removing redundant `IList` and `ICollection` members. - Add local settings, IDE configuration, and Omnisharp configuration files for project customization and exclusion patterns.
1 parent e331ef1 commit 6143d42

6 files changed

Lines changed: 62 additions & 94 deletions

File tree

.claude/settings.local.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(dotnet build:*)",
5+
"Bash(dotnet test:*)",
6+
"Bash(taskkill:*)",
7+
"Bash(del \"D:\\\\GitHub\\\\Porticle.Grpc.TypeMapper\\\\Source\\\\Porticle.Grpc.TypeMapper\\\\bin\\\\Debug\\\\net9.0\\\\Porticle.Grpc.TypeMapper.dll\")"
8+
]
9+
}
10+
}

Source/.idea/.idea.Porticle.Grpc/.idea/AndroidProjectSystem.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Source/Porticle.Grpc.TypeMapper/ClassVisitor.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ public class ClassVisitor(TaskLoggingHelper log, bool wrapAllNonNullableStrings,
3131
var methodVisitor = new MethodVisitor(propertyVisitor.ReplaceProps);
3232
node = (ClassDeclarationSyntax)methodVisitor.Visit(node);
3333

34+
// Add ICustomDiagnosticMessage implementation for message classes
35+
// Note: The interface is added to the base list via text replacement in ProtoPostProcessor
36+
// because Roslyn's AddBaseListTypes breaks #if/#endif preprocessor directives in the base list.
37+
var isMessageClass = node.BaseList?.Types.Any(t => t.ToString().Contains("IMessage")) ?? false;
38+
if (isMessageClass)
39+
{
40+
node = node.AddMembers(MethodFromSource("public string ToDiagnosticString() { return System.Text.Json.JsonSerializer.Serialize(this); }"));
41+
}
42+
3443
return node;
3544
}
3645

@@ -49,4 +58,12 @@ private static InterfaceDeclarationSyntax InterfaceFromSource(string classCode)
4958
var nestedClass = root.DescendantNodes().OfType<InterfaceDeclarationSyntax>().Single();
5059
return nestedClass.WithLeadingTrivia(SyntaxFactory.CarriageReturnLineFeed).WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed);
5160
}
61+
62+
private static MethodDeclarationSyntax MethodFromSource(string methodCode)
63+
{
64+
var syntaxTree = CSharpSyntaxTree.ParseText("class _ { " + methodCode + " }");
65+
var root = syntaxTree.GetRoot();
66+
var method = root.DescendantNodes().OfType<MethodDeclarationSyntax>().Single();
67+
return method.WithLeadingTrivia(SyntaxFactory.CarriageReturnLineFeed).WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed);
68+
}
5269
}

Source/Porticle.Grpc.TypeMapper/ListWrappers.cs

Lines changed: 4 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
public static class ListWrappers
44
{
55
public static string IListWithRangeAdd = """
6-
public interface IListWithRangeAdd<T> : System.Collections.Generic.IList<T>, System.Collections.IList
6+
public interface IListWithRangeAdd<T> : System.Collections.Generic.IList<T>
77
{
8-
void Add(IEnumerable<T> items);
8+
void Add(IEnumerable<T> items);
99
}
1010
""";
1111

@@ -64,13 +64,9 @@ public bool Remove(System.Guid item)
6464
}
6565
6666
public int Count => _internList.Count;
67-
68-
int System.Collections.ICollection.Count => _internList.Count;
69-
67+
7068
public bool IsReadOnly => _internList.IsReadOnly;
71-
72-
bool System.Collections.IList.IsReadOnly => _internList.IsReadOnly;
73-
69+
7470
public int IndexOf(System.Guid item)
7571
{
7672
return _internList.IndexOf(item.ToString("D"));
@@ -91,91 +87,6 @@ public System.Guid this[int index]
9187
get => System.Guid.Parse(_internList[index]);
9288
set => _internList[index] = value.ToString("D");
9389
}
94-
95-
System.Guid System.Collections.Generic.IList<System.Guid>.this[int index]
96-
{
97-
get => System.Guid.Parse(_internList[index]);
98-
set => _internList[index] = value.ToString("D");
99-
}
100-
101-
// IList (non-generic) explicit implementation
102-
int System.Collections.IList.Add(object value)
103-
{
104-
if (value is System.Guid guid)
105-
{
106-
Add(guid);
107-
return Count - 1;
108-
}
109-
throw new System.ArgumentException("Value must be of type System.Guid", nameof(value));
110-
}
111-
112-
bool System.Collections.IList.Contains(object value)
113-
{
114-
if (value is System.Guid guid)
115-
{
116-
return Contains(guid);
117-
}
118-
return false;
119-
}
120-
121-
int System.Collections.IList.IndexOf(object value)
122-
{
123-
if (value is System.Guid guid)
124-
{
125-
return IndexOf(guid);
126-
}
127-
return -1;
128-
}
129-
130-
void System.Collections.IList.Insert(int index, object value)
131-
{
132-
if (value is System.Guid guid)
133-
{
134-
Insert(index, guid);
135-
return;
136-
}
137-
throw new System.ArgumentException("Value must be of type System.Guid", nameof(value));
138-
}
139-
140-
void System.Collections.IList.Remove(object value)
141-
{
142-
if (value is System.Guid guid)
143-
{
144-
Remove(guid);
145-
}
146-
}
147-
148-
bool System.Collections.IList.IsFixedSize => false;
149-
150-
object System.Collections.IList.this[int index]
151-
{
152-
get => System.Guid.Parse(_internList[index]);
153-
set
154-
{
155-
if (value is System.Guid guid)
156-
{
157-
_internList[index] = guid.ToString("D");
158-
return;
159-
}
160-
throw new System.ArgumentException("Value must be of type System.Guid", nameof(value));
161-
}
162-
}
163-
164-
// ICollection (non-generic) explicit implementation
165-
void System.Collections.ICollection.CopyTo(System.Array array, int index)
166-
{
167-
if (array is System.Guid[] guidArray)
168-
{
169-
CopyTo(guidArray, index);
170-
return;
171-
}
172-
var guids = System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Select(_internList, System.Guid.Parse));
173-
System.Array.Copy(guids, 0, array, index, guids.Length);
174-
}
175-
176-
bool System.Collections.ICollection.IsSynchronized => false;
177-
178-
object System.Collections.ICollection.SyncRoot => ((System.Collections.ICollection)_internList).SyncRoot;
17990
}
18091
""";
18192
}

Source/Porticle.Grpc.TypeMapper/ProtoPostProcessor.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,14 @@ public override bool Execute()
5151
var classVisitor = new ClassVisitor(Log, WrapAllNonNullableStrings, WrapAllNullableStringValues);
5252
root = classVisitor.Visit(root);
5353

54-
File.WriteAllText(filePath, root.ToFullString());
54+
var output = root.ToFullString();
55+
56+
// Add ICustomDiagnosticMessage to message class base lists.
57+
// This is done via text replacement because Roslyn's AddBaseListTypes
58+
// breaks #if/#endif preprocessor directives in the generated base list.
59+
output = Regex.Replace(output, @"(: pb::IMessage<\w+>)(?!, pb::ICustomDiagnosticMessage)", "$1, pb::ICustomDiagnosticMessage");
60+
61+
File.WriteAllText(filePath, output);
5562
}
5663
}
5764

Source/omnisharp.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"RoslynExtensionsOptions": {
3+
"EnableAnalyzersSupport": false,
4+
"EnableDecompilationSupport": false
5+
},
6+
"msbuild": {
7+
"loadProjectsOnDemand": true
8+
},
9+
"fileOptions": {
10+
"systemExcludeSearchPatterns": [
11+
"**/bin/**/*",
12+
"**/obj/**/*",
13+
"**/.git/**/*",
14+
"**/node_modules/**/*"
15+
]
16+
}
17+
}

0 commit comments

Comments
 (0)