22using LayeredCraft . DynamoMapper . Generator . PropertyMapping . Models ;
33using LayeredCraft . DynamoMapper . Runtime ;
44using Microsoft . CodeAnalysis ;
5- using WellKnownType = LayeredCraft . DynamoMapper . Generator . WellKnownTypes . WellKnownTypeData . WellKnownType ;
5+ using WellKnownType =
6+ LayeredCraft . DynamoMapper . Generator . WellKnownTypes . WellKnownTypeData . WellKnownType ;
67
78namespace LayeredCraft . DynamoMapper . Generator . PropertyMapping ;
89
@@ -16,6 +17,7 @@ internal readonly record struct ElementTypeValidationResult(
1617 NestedMappingInfo ? NestedMapping ,
1718 DiagnosticInfo ? Error
1819 ) ;
20+
1921 /// <summary>
2022 /// Analyzes a type to determine if it's a collection type and returns metadata about it.
2123 /// </summary>
@@ -44,8 +46,10 @@ internal readonly record struct ElementTypeValidationResult(
4446 return null ;
4547
4648 // Check for Dictionary<TKey, TValue> or IDictionary<TKey, TValue>
47- var dictionaryType = context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_Dictionary_2 ) ;
48- var iDictionaryType = context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_IDictionary_2 ) ;
49+ var dictionaryType =
50+ context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_Dictionary_2 ) ;
51+ var iDictionaryType =
52+ context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_IDictionary_2 ) ;
4953
5054 if ( IsOrImplements ( namedType , dictionaryType ) || IsOrImplements ( namedType , iDictionaryType ) )
5155 {
@@ -66,7 +70,8 @@ internal readonly record struct ElementTypeValidationResult(
6670 }
6771
6872 // Check for HashSet<T> or ISet<T>
69- var hashSetType = context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_HashSet_1 ) ;
73+ var hashSetType =
74+ context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_HashSet_1 ) ;
7075 var iSetType = context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_ISet_1 ) ;
7176
7277 if ( IsOrImplements ( namedType , hashSetType ) || IsOrImplements ( namedType , iSetType ) )
@@ -92,14 +97,16 @@ internal readonly record struct ElementTypeValidationResult(
9297
9398 // Check for List<T>, IList<T>, ICollection<T>, or IEnumerable<T>
9499 var listType = context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_List_1 ) ;
95- var iListType = context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_IList_1 ) ;
96- var iCollectionType = context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_ICollection_1 ) ;
97- var iEnumerableType = context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_IEnumerable_1 ) ;
98-
99- if ( IsOrImplements ( namedType , listType )
100- || IsOrImplements ( namedType , iListType )
101- || IsOrImplements ( namedType , iCollectionType )
102- || IsOrImplements ( namedType , iEnumerableType ) )
100+ var iListType =
101+ context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_IList_1 ) ;
102+ var iCollectionType =
103+ context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_ICollection_1 ) ;
104+ var iEnumerableType =
105+ context . WellKnownTypes . Get ( WellKnownType . System_Collections_Generic_IEnumerable_1 ) ;
106+
107+ if ( IsOrImplements ( namedType , listType ) || IsOrImplements ( namedType , iListType ) ||
108+ IsOrImplements ( namedType , iCollectionType ) ||
109+ IsOrImplements ( namedType , iEnumerableType ) )
103110 {
104111 // Extract element type: List<T>
105112 if ( namedType . TypeArguments . Length == 1 )
@@ -141,8 +148,7 @@ internal static bool IsValidElementType(ITypeSymbol elementType, GeneratorContex
141148 /// <param name="context">The generator context.</param>
142149 /// <returns>A tuple of (isValid, nestedMappingInfo). nestedMappingInfo is null for primitives.</returns>
143150 internal static ElementTypeValidationResult ValidateElementType (
144- ITypeSymbol elementType ,
145- GeneratorContext context
151+ ITypeSymbol elementType , GeneratorContext context
146152 )
147153 {
148154 var nestedContext = NestedAnalysisContext . Create ( context , context . MapperRegistry ) ;
@@ -161,16 +167,17 @@ GeneratorContext context
161167 /// <param name="nestedContext">The nested analysis context to preserve ancestor tracking.</param>
162168 /// <returns>A tuple of (isValid, nestedMappingInfo). nestedMappingInfo is null for primitives.</returns>
163169 internal static ElementTypeValidationResult ValidateElementType (
164- ITypeSymbol elementType ,
165- NestedAnalysisContext nestedContext
170+ ITypeSymbol elementType , NestedAnalysisContext nestedContext
166171 )
167172 {
168173 var context = nestedContext . Context ;
169174
170175 // Unwrap Nullable<T> - nullable elements are allowed
171176 var underlyingType = elementType ;
172- if ( elementType is INamedTypeSymbol { OriginalDefinition . SpecialType : SpecialType . System_Nullable_T } nullableType
173- && nullableType . TypeArguments . Length == 1 )
177+ if ( elementType is INamedTypeSymbol
178+ {
179+ OriginalDefinition . SpecialType : SpecialType . System_Nullable_T ,
180+ } nullableType && nullableType . TypeArguments . Length == 1 )
174181 {
175182 underlyingType = nullableType . TypeArguments [ 0 ] ;
176183 }
@@ -200,7 +207,8 @@ NestedAnalysisContext nestedContext
200207 return new ElementTypeValidationResult ( true , null , null ) ;
201208
202209 // DateTimeOffset
203- var dateTimeOffsetType = context . WellKnownTypes . Get ( WellKnownType . System_DateTimeOffset ) ;
210+ var dateTimeOffsetType =
211+ context . WellKnownTypes . Get ( WellKnownType . System_DateTimeOffset ) ;
204212 if ( SymbolEqualityComparer . Default . Equals ( namedType , dateTimeOffsetType ) )
205213 return new ElementTypeValidationResult ( true , null , null ) ;
206214
@@ -215,8 +223,8 @@ NestedAnalysisContext nestedContext
215223 }
216224
217225 // Check for byte[] (valid for BS - Binary Set)
218- if ( underlyingType is IArrayTypeSymbol arrayType
219- && arrayType . ElementType . SpecialType == SpecialType . System_Byte )
226+ if ( underlyingType is IArrayTypeSymbol arrayType &&
227+ arrayType . ElementType . SpecialType == SpecialType . System_Byte )
220228 {
221229 return new ElementTypeValidationResult ( true , null , null ) ;
222230 }
@@ -225,12 +233,10 @@ NestedAnalysisContext nestedContext
225233 if ( Analyze ( underlyingType , context ) is not null )
226234 return new ElementTypeValidationResult ( false , null , null ) ;
227235
228- // Try to analyze as a nested object
229- var nestedResult = NestedObjectTypeAnalyzer . Analyze (
230- underlyingType ,
231- "element" , // property name doesn't matter for element type analysis
232- nestedContext
233- ) ;
236+ // Try to analyze as a nested object. Use AnalyzeElementType instead of Analyze so the
237+ // caller-supplied path prefix is not further modified by a dummy property name.
238+ var nestedResult =
239+ NestedObjectTypeAnalyzer . AnalyzeElementType ( underlyingType , nestedContext ) ;
234240
235241 if ( ! nestedResult . IsSuccess )
236242 return new ElementTypeValidationResult ( false , null , nestedResult . Error ) ;
@@ -254,8 +260,10 @@ NestedAnalysisContext nestedContext
254260 {
255261 // Unwrap Nullable<T> if present
256262 var underlyingType = elementType ;
257- if ( elementType is INamedTypeSymbol { OriginalDefinition . SpecialType : SpecialType . System_Nullable_T } nullableType
258- && nullableType . TypeArguments . Length == 1 )
263+ if ( elementType is INamedTypeSymbol
264+ {
265+ OriginalDefinition . SpecialType : SpecialType . System_Nullable_T ,
266+ } nullableType && nullableType . TypeArguments . Length == 1 )
259267 {
260268 underlyingType = nullableType . TypeArguments [ 0 ] ;
261269 }
@@ -278,8 +286,8 @@ NestedAnalysisContext nestedContext
278286 }
279287
280288 // byte[] → BS
281- if ( underlyingType is IArrayTypeSymbol arrayType
282- && arrayType . ElementType . SpecialType == SpecialType . System_Byte )
289+ if ( underlyingType is IArrayTypeSymbol arrayType &&
290+ arrayType . ElementType . SpecialType == SpecialType . System_Byte )
283291 {
284292 return DynamoKind . BS ;
285293 }
@@ -291,7 +299,9 @@ NestedAnalysisContext nestedContext
291299 /// <summary>
292300 /// Checks if a type matches or implements a generic type definition.
293301 /// </summary>
294- private static bool IsOrImplements ( INamedTypeSymbol type , INamedTypeSymbol ? genericTypeDefinition )
302+ private static bool IsOrImplements (
303+ INamedTypeSymbol type , INamedTypeSymbol ? genericTypeDefinition
304+ )
295305 {
296306 if ( genericTypeDefinition == null )
297307 return false ;
@@ -301,7 +311,8 @@ private static bool IsOrImplements(INamedTypeSymbol type, INamedTypeSymbol? gene
301311 return true ;
302312
303313 // Check if any interface matches
304- return type . AllInterfaces . Any ( i =>
305- SymbolEqualityComparer . Default . Equals ( i . OriginalDefinition , genericTypeDefinition ) ) ;
314+ return type . AllInterfaces . Any (
315+ i => SymbolEqualityComparer . Default . Equals ( i . OriginalDefinition , genericTypeDefinition )
316+ ) ;
306317 }
307318}
0 commit comments