Skip to content

Commit aaa1000

Browse files
committed
add required member judgment for base type
1 parent cc791d3 commit aaa1000

File tree

2 files changed

+167
-95
lines changed

2 files changed

+167
-95
lines changed

src/SourceGeneration.Reflection.SourceGenerator/ReflectionSourceGenerator.Emit.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,13 +391,32 @@ private static void EmitConstructor(CSharpCodeBuilder builder, SourceTypeInfo ty
391391
!type.IsRefLikeType &&
392392
!constructor.Parameters.Any(x => x.IsParameterTypeRefLike || x.IsParameterTypePointer) &&
393393
constructor.Accessibility != Accessibility.Private && constructor.Accessibility != Accessibility.Protected &&
394-
!type.Properties.Any(x => x.IsRequired))
394+
!type.Properties.Any(x => x.IsRequired) && !type.Fields.Any(x => x.IsRequired) && !type.HasBaseRequiredMembers)
395395
{
396396
builder.AppendIndent();
397397
builder.Append($"Invoke = static (parameters) => new {type.FullGlobalName}(");
398398
AppendMethodArguments(builder, constructor.Parameters);
399399
builder.Append(")");
400400
builder.AppendLine();
401+
402+
//if (type.Fields.Any(x=>x.IsRequired) || type.Properties.Any(x => x.IsRequired) || type.BaseRequiredMembers.Count > 0)
403+
//{
404+
// builder.AppendBlock(() =>
405+
// {
406+
// foreach (var property in type.Properties.Where(x => x.IsRequired))
407+
// {
408+
// builder.AppendLine($"{property.Name} = {property.DefaultValueExpression ?? "default"},");
409+
// }
410+
// foreach (var field in type.Fields.Where(x => x.IsRequired))
411+
// {
412+
// builder.AppendLine($"{field.Name} = {field.DefaultValueExpression ?? "default"},");
413+
// }
414+
// foreach (var property in type.BaseRequiredMembers)
415+
// {
416+
// builder.AppendLine($"{property.Key} = {property.Value ?? "default"},");
417+
// }
418+
// });
419+
//}
401420
}
402421

403422
}, ",");

src/SourceGeneration.Reflection.SourceGenerator/ReflectionSourceGenerator.Parse.cs

Lines changed: 147 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
namespace SourceGeneration.Reflection;
99

10+
#pragma warning disable IDE0305
11+
1012
public partial class ReflectionSourceGenerator
1113
{
1214
private static readonly SymbolDisplayFormat GlobalTypeDisplayFormat = new SymbolDisplayFormat(
@@ -34,11 +36,11 @@ private static IEnumerable<SourceTypeInfo> Parse(IAssemblySymbol assemblySymbol,
3436

3537
if (typeSymbol.TypeKind == TypeKind.Enum)
3638
{
37-
yield return PaseEnumType(typeSymbol);
39+
yield return PaseEnumType(typeSymbol, cancellationToken);
3840
}
3941
else
4042
{
41-
yield return ParseClassType(typeSymbol);
43+
yield return ParseClassType(typeSymbol, cancellationToken);
4244
}
4345

4446
if (typeSymbol.BaseType != null && typeSymbol.BaseType.ContainingAssembly.Equals(assemblySymbol, SymbolEqualityComparer.Default) && !typeSymbols.Contains(typeSymbol.BaseType, SymbolEqualityComparer.Default))
@@ -51,7 +53,7 @@ private static IEnumerable<SourceTypeInfo> Parse(IAssemblySymbol assemblySymbol,
5153
}
5254
}
5355

54-
private static SourceTypeInfo PaseEnumType(INamedTypeSymbol typeSymbol)
56+
private static SourceTypeInfo PaseEnumType(INamedTypeSymbol typeSymbol, CancellationToken cancellationToken)
5557
{
5658
var fullname = typeSymbol.ToDisplayString(GlobalTypeDisplayFormat);
5759
SourceTypeInfo typeInfo = new()
@@ -67,13 +69,14 @@ private static SourceTypeInfo PaseEnumType(INamedTypeSymbol typeSymbol)
6769

6870
foreach (var field in typeSymbol.GetMembers().OfType<IFieldSymbol>())
6971
{
70-
typeInfo.Fields.Add(CreateField(field));
72+
cancellationToken.ThrowIfCancellationRequested();
73+
typeInfo.Fields.Add(CreateField(field, cancellationToken));
7174
}
7275

7376
return typeInfo;
7477
}
7578

76-
private static SourceTypeInfo ParseClassType(INamedTypeSymbol typeSymbol)
79+
private static SourceTypeInfo ParseClassType(INamedTypeSymbol typeSymbol, CancellationToken cancellationToken)
7780
{
7881
string fullname;
7982
bool isGenericTypeDefinition;
@@ -105,119 +108,167 @@ private static SourceTypeInfo ParseClassType(INamedTypeSymbol typeSymbol)
105108
Accessibility = typeSymbol.DeclaredAccessibility,
106109
};
107110

111+
var baseType = typeSymbol.BaseType;
112+
while (baseType != null)
113+
{
114+
foreach (var member in baseType.GetMembers().Where(x => !x.IsAbstract && !x.IsOverride))
115+
{
116+
if (member is IPropertySymbol property)
117+
{
118+
if (property.IsRequired)
119+
{
120+
typeInfo.HasBaseRequiredMembers = true;
121+
break;
122+
//var value = property.GetInitializeValue(cancellationToken);
123+
//typeInfo.BaseRequiredMembers.Add(property.Name, value);
124+
}
125+
}
126+
else if (member is IFieldSymbol field)
127+
{
128+
if (field.IsRequired)
129+
{
130+
typeInfo.HasBaseRequiredMembers = true;
131+
break;
132+
//var value = field.GetInitializeValue(cancellationToken);
133+
//typeInfo.BaseRequiredMembers.Add(field.Name, value);
134+
}
135+
}
136+
}
137+
baseType = baseType.BaseType;
138+
}
139+
108140

109141
var members = typeSymbol.GetMembers();
110142

111143
foreach (var field in members.OfType<IFieldSymbol>())
112144
{
113-
typeInfo.Fields.Add(CreateField(field));
145+
cancellationToken.ThrowIfCancellationRequested();
146+
typeInfo.Fields.Add(CreateField(field, cancellationToken));
114147
}
115148

116149
foreach (var property in members.OfType<IPropertySymbol>())
117150
{
118-
SourcePropertyInfo propertyInfo = new()
119-
{
120-
Name = property.Name,
121-
Accessibility = property.DeclaredAccessibility,
122-
NullableAnnotation = property.NullableAnnotation,
123-
IsVirtual = property.IsVirtual,
124-
IsRequired = property.IsRequired,
125-
IsAbstract = property.IsAbstract,
126-
IsStatic = property.IsStatic,
127-
IsIndexer = property.IsIndexer,
128-
CanRead = property.GetMethod != null,
129-
CanWrite = property.SetMethod != null,
130-
IsInitOnly = property.SetMethod?.IsInitOnly == true,
131-
GetMethodAccessibility = property.GetMethod?.DeclaredAccessibility ?? Accessibility.NotApplicable,
132-
SetMethodAccessibility = property.SetMethod?.DeclaredAccessibility ?? Accessibility.NotApplicable,
133-
134-
IsGenericDictionaryType = property.Type.IsCompliantGenericDictionaryInterface(),
135-
IsGenericEnumerableType = property.Type.IsCompliantGenericEnumerableInterface(),
136-
137-
PropertyType = property.Type.ToDisplayString(GlobalTypeDisplayFormat),
138-
Parameters = property.Parameters.Select(x => new SourceParameterInfo
139-
{
140-
Name = x.Name,
141-
ParameterType = x.Type.ToDisplayString(GlobalTypeDisplayFormat),
142-
NullableAnnotation = x.NullableAnnotation,
143-
HasDefaultValue = x.HasExplicitDefaultValue,
144-
HasNestedTypeParameter = x.Type.TypeKind == TypeKind.TypeParameter,
145-
DefaultValue = x.HasExplicitDefaultValue ? x.ExplicitDefaultValue : null,
146-
}).ToList(),
147-
};
148-
149-
typeInfo.Properties.Add(propertyInfo);
151+
cancellationToken.ThrowIfCancellationRequested();
152+
typeInfo.Properties.Add(CreateProperty(property, cancellationToken));
150153
}
151154

152155
foreach (var constructor in typeSymbol.Constructors)
153156
{
154-
SourceConstructorInfo constructorInfo = new()
155-
{
156-
Name = constructor.Name,
157-
IsStatic = constructor.IsStatic,
158-
Accessibility = constructor.DeclaredAccessibility,
159-
Parameters = constructor.Parameters.Select(x => new SourceParameterInfo
160-
{
161-
Name = x.Name,
162-
ParameterType = x.Type.ToDisplayString(GlobalTypeDisplayFormat),
163-
IsParameterTypeRefLike = x.Type.IsRefLikeType,
164-
IsParameterTypePointer = x.Type.Kind == SymbolKind.PointerType,
165-
NullableAnnotation = x.NullableAnnotation,
166-
HasDefaultValue = x.HasExplicitDefaultValue,
167-
HasNestedTypeParameter = x.Type.TypeKind == TypeKind.TypeParameter,
168-
DefaultValue = x.HasExplicitDefaultValue ? x.ExplicitDefaultValue : null,
169-
}).ToList(),
170-
};
171-
typeInfo.Constructors.Add(constructorInfo);
157+
cancellationToken.ThrowIfCancellationRequested();
158+
typeInfo.Constructors.Add(CreateConstructor(constructor));
172159
}
173160

174161
foreach (var method in members.OfType<IMethodSymbol>().Where(x => x.MethodKind == MethodKind.Ordinary && !x.IsImplicitlyDeclared))
175162
{
176-
SourceMethodInfo methodInfo = new()
177-
{
178-
Name = method.Name,
179-
Accessibility = method.DeclaredAccessibility,
180-
IsOverride = method.IsOverride,
181-
IsVirtual = method.IsVirtual,
182-
IsAbstract = method.IsAbstract,
183-
IsStatic = method.IsStatic,
184-
IsGenericMethod = method.IsGenericMethod,
185-
ReturnType = method.ReturnsVoid ? "void" : method.ReturnType.HasTypeParameter() ? null : method.ReturnType.ToDisplayString(GlobalTypeDisplayFormat),
186-
ReturnNullableAnnotation = method.ReturnNullableAnnotation,
187-
TypeParameters = method.TypeParameters.Select(x => new SourceTypeParameterInfo
188-
{
189-
Name = x.Name,
190-
HasUnmanagedTypeConstraint = x.HasUnmanagedTypeConstraint,
191-
HasValueTypeConstraint = x.HasValueTypeConstraint,
192-
HasTypeParameterInConstraintTypes = x.ConstraintTypes.Any(x => x.HasTypeParameter()),
193-
ConstraintTypes = x.ConstraintTypes.Select(x => x.ToDisplayString(GlobalTypeDisplayFormat)).ToArray(),
194-
}).ToArray(),
195-
Parameters = method.Parameters.Select(x => new SourceParameterInfo
196-
{
197-
Name = x.Name,
198-
ParameterType = x.Type.ToDisplayString(GlobalTypeDisplayFormat),
199-
IsParameterTypeRefLike = x.Type.IsRefLikeType,
200-
IsParameterTypePointer = x.Type.Kind == SymbolKind.PointerType,
201-
NullableAnnotation = x.NullableAnnotation,
202-
HasDefaultValue = x.HasExplicitDefaultValue,
203-
IsTypeParameter = x.Type.Kind == SymbolKind.TypeParameter,
204-
HasNestedTypeParameter = x.Type.HasTypeParameter(),
205-
IsRef = x.RefKind == RefKind.Ref,
206-
IsOut = x.RefKind == RefKind.Out,
207-
DefaultValue = x.HasExplicitDefaultValue ? x.ExplicitDefaultValue : null,
208-
DisplayType = x.Type.ToReflectionDisplayString()
209-
}).ToList(),
210-
};
211-
212-
typeInfo.Methods.Add(methodInfo);
163+
cancellationToken.ThrowIfCancellationRequested();
164+
typeInfo.Methods.Add(CreateMethod(method));
213165
}
214166

215167
return typeInfo;
216168
}
217169

170+
private static SourceMethodInfo CreateMethod(IMethodSymbol method)
171+
{
172+
return new()
173+
{
174+
Name = method.Name,
175+
Accessibility = method.DeclaredAccessibility,
176+
IsOverride = method.IsOverride,
177+
IsVirtual = method.IsVirtual,
178+
IsAbstract = method.IsAbstract,
179+
IsStatic = method.IsStatic,
180+
IsGenericMethod = method.IsGenericMethod,
181+
ReturnType = method.ReturnsVoid ? "void" : method.ReturnType.HasTypeParameter() ? null : method.ReturnType.ToDisplayString(GlobalTypeDisplayFormat),
182+
ReturnNullableAnnotation = method.ReturnNullableAnnotation,
183+
TypeParameters = method.TypeParameters.Select(x => new SourceTypeParameterInfo
184+
{
185+
Name = x.Name,
186+
HasUnmanagedTypeConstraint = x.HasUnmanagedTypeConstraint,
187+
HasValueTypeConstraint = x.HasValueTypeConstraint,
188+
HasTypeParameterInConstraintTypes = x.ConstraintTypes.Any(x => x.HasTypeParameter()),
189+
ConstraintTypes = x.ConstraintTypes.Select(x => x.ToDisplayString(GlobalTypeDisplayFormat)).ToArray(),
190+
}).ToArray(),
191+
Parameters = method.Parameters.Select(x => new SourceParameterInfo
192+
{
193+
Name = x.Name,
194+
ParameterType = x.Type.ToDisplayString(GlobalTypeDisplayFormat),
195+
IsParameterTypeRefLike = x.Type.IsRefLikeType,
196+
IsParameterTypePointer = x.Type.Kind == SymbolKind.PointerType,
197+
NullableAnnotation = x.NullableAnnotation,
198+
HasDefaultValue = x.HasExplicitDefaultValue,
199+
IsTypeParameter = x.Type.Kind == SymbolKind.TypeParameter,
200+
HasNestedTypeParameter = x.Type.HasTypeParameter(),
201+
IsRef = x.RefKind == RefKind.Ref,
202+
IsOut = x.RefKind == RefKind.Out,
203+
DefaultValue = x.HasExplicitDefaultValue ? x.ExplicitDefaultValue : null,
204+
DisplayType = x.Type.ToReflectionDisplayString()
205+
}).ToList(),
206+
};
207+
}
208+
209+
private static SourceConstructorInfo CreateConstructor(IMethodSymbol constructor)
210+
{
211+
return new()
212+
{
213+
Name = constructor.Name,
214+
IsStatic = constructor.IsStatic,
215+
Accessibility = constructor.DeclaredAccessibility,
216+
Parameters = constructor.Parameters.Select(x => new SourceParameterInfo
217+
{
218+
Name = x.Name,
219+
ParameterType = x.Type.ToDisplayString(GlobalTypeDisplayFormat),
220+
IsParameterTypeRefLike = x.Type.IsRefLikeType,
221+
IsParameterTypePointer = x.Type.Kind == SymbolKind.PointerType,
222+
NullableAnnotation = x.NullableAnnotation,
223+
HasDefaultValue = x.HasExplicitDefaultValue,
224+
HasNestedTypeParameter = x.Type.TypeKind == TypeKind.TypeParameter,
225+
DefaultValue = x.HasExplicitDefaultValue ? x.ExplicitDefaultValue : null,
226+
}).ToList(),
227+
};
228+
}
229+
230+
private static SourcePropertyInfo CreateProperty(IPropertySymbol property, CancellationToken cancellationToken)
231+
{
232+
//string defaultValueExpression = property.IsRequired ? property.GetInitializeValue(cancellationToken) :null;
233+
234+
return new()
235+
{
236+
Name = property.Name,
237+
Accessibility = property.DeclaredAccessibility,
238+
NullableAnnotation = property.NullableAnnotation,
239+
IsVirtual = property.IsVirtual,
240+
IsRequired = property.IsRequired,
241+
IsAbstract = property.IsAbstract,
242+
IsStatic = property.IsStatic,
243+
IsIndexer = property.IsIndexer,
244+
CanRead = property.GetMethod != null,
245+
CanWrite = property.SetMethod != null,
246+
IsInitOnly = property.SetMethod?.IsInitOnly == true,
247+
GetMethodAccessibility = property.GetMethod?.DeclaredAccessibility ?? Accessibility.NotApplicable,
248+
SetMethodAccessibility = property.SetMethod?.DeclaredAccessibility ?? Accessibility.NotApplicable,
249+
250+
IsGenericDictionaryType = property.Type.IsCompliantGenericDictionaryInterface(),
251+
IsGenericEnumerableType = property.Type.IsCompliantGenericEnumerableInterface(),
252+
253+
//DefaultValueExpression = defaultValueExpression,
218254

219-
private static SourceFieldInfo CreateField(IFieldSymbol field)
255+
PropertyType = property.Type.ToDisplayString(GlobalTypeDisplayFormat),
256+
Parameters = property.Parameters.Select(x => new SourceParameterInfo
257+
{
258+
Name = x.Name,
259+
ParameterType = x.Type.ToDisplayString(GlobalTypeDisplayFormat),
260+
NullableAnnotation = x.NullableAnnotation,
261+
HasDefaultValue = x.HasExplicitDefaultValue,
262+
HasNestedTypeParameter = x.Type.TypeKind == TypeKind.TypeParameter,
263+
DefaultValue = x.HasExplicitDefaultValue ? x.ExplicitDefaultValue : null,
264+
}).ToList(),
265+
};
266+
}
267+
268+
private static SourceFieldInfo CreateField(IFieldSymbol field, CancellationToken cancellationToken)
220269
{
270+
//string defaultValueExpression = field.IsRequired ? field.GetInitializeValue(cancellationToken) : null;
271+
221272
return new()
222273
{
223274
Name = field.Name,
@@ -233,6 +284,8 @@ private static SourceFieldInfo CreateField(IFieldSymbol field)
233284
IsGenericEnumerableType = field.Type.IsCompliantGenericEnumerableInterface(),
234285

235286
FieldType = field.Type.ToDisplayString(GlobalTypeDisplayFormat),
287+
288+
//DefaultValueExpression = defaultValueExpression,
236289
};
237290
}
238291

0 commit comments

Comments
 (0)