5
5
using System ;
6
6
using System . Collections . Immutable ;
7
7
using System . Linq ;
8
+ using System . Threading ;
8
9
using Microsoft . CodeAnalysis ;
10
+ using Microsoft . CodeAnalysis . CSharp . Syntax ;
9
11
using Microsoft . CodeAnalysis . Operations ;
10
12
11
13
namespace CommunityToolkit . Mvvm . SourceGenerators . ComponentModel . Models ;
@@ -62,21 +64,28 @@ public static TypedConstantInfo From(TypedConstant arg)
62
64
/// <summary>
63
65
/// Creates a new <see cref="TypedConstantInfo"/> instance from a given <see cref="IOperation"/> value.
64
66
/// </summary>
65
- /// <param name="arg">The input <see cref="IOperation"/> value.</param>
66
- /// <returns>A <see cref="TypedConstantInfo"/> instance representing <paramref name="arg"/>.</returns>
67
+ /// <param name="operation">The input <see cref="IOperation"/> value.</param>
68
+ /// <param name="semanticModel">The <see cref="SemanticModel"/> that was used to retrieve <paramref name="operation"/>.</param>
69
+ /// <param name="expression">The <see cref="ExpressionSyntax"/> that <paramref name="operation"/> was retrieved from.</param>
70
+ /// <param name="token">The cancellation token for the current operation.</param>
71
+ /// <returns>A <see cref="TypedConstantInfo"/> instance representing <paramref name="operation"/>.</returns>
67
72
/// <exception cref="ArgumentException">Thrown if the input argument is not valid.</exception>
68
- public static TypedConstantInfo From ( IOperation arg )
73
+ public static TypedConstantInfo From (
74
+ IOperation operation ,
75
+ SemanticModel semanticModel ,
76
+ ExpressionSyntax expression ,
77
+ CancellationToken token )
69
78
{
70
- if ( arg . ConstantValue . HasValue )
79
+ if ( operation . ConstantValue . HasValue )
71
80
{
72
81
// Enum values are constant but need to be checked explicitly in this case
73
- if ( arg . Type ? . TypeKind is TypeKind . Enum )
82
+ if ( operation . Type ? . TypeKind is TypeKind . Enum )
74
83
{
75
- return new Enum ( arg . Type ! . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) , arg . ConstantValue . Value ! ) ;
84
+ return new Enum ( operation . Type ! . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) , operation . ConstantValue . Value ! ) ;
76
85
}
77
86
78
87
// Handle all other constant literals normally
79
- return arg . ConstantValue . Value switch
88
+ return operation . ConstantValue . Value switch
80
89
{
81
90
null => new Null ( ) ,
82
91
string text => new Primitive . String ( text ) ,
@@ -96,21 +105,42 @@ public static TypedConstantInfo From(IOperation arg)
96
105
} ;
97
106
}
98
107
99
- if ( arg is ITypeOfOperation typeOfOperation )
108
+ if ( operation is ITypeOfOperation typeOfOperation )
100
109
{
101
110
return new Type ( typeOfOperation . TypeOperand . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ) ;
102
111
}
103
112
104
- if ( arg is IArrayCreationOperation arrayCreationOperation )
113
+ if ( operation is IArrayCreationOperation )
105
114
{
106
- string ? elementTypeName = ( ( IArrayTypeSymbol ? ) arg . Type ) ? . ElementType . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ;
115
+ string ? elementTypeName = ( ( IArrayTypeSymbol ? ) operation . Type ) ? . ElementType . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ;
107
116
108
117
// If the element type is not available (since the attribute wasn't checked), just default to object
109
118
elementTypeName ??= "object" ;
110
119
111
- ImmutableArray < TypedConstantInfo > items = ImmutableArray < TypedConstantInfo > . Empty ; // TODO
120
+ InitializerExpressionSyntax ? initializerExpression =
121
+ ( expression as ImplicitArrayCreationExpressionSyntax ) ? . Initializer
122
+ ?? ( expression as ArrayCreationExpressionSyntax ) ? . Initializer ;
112
123
113
- return new Array ( elementTypeName , items ) ;
124
+ // No initializer found, just return an empty array
125
+ if ( initializerExpression is null )
126
+ {
127
+ return new Array ( elementTypeName , ImmutableArray < TypedConstantInfo > . Empty ) ;
128
+ }
129
+
130
+ ImmutableArray < TypedConstantInfo > . Builder items = ImmutableArray . CreateBuilder < TypedConstantInfo > ( initializerExpression . Expressions . Count ) ;
131
+
132
+ // Enumerate all array elements and extract serialized info for them
133
+ foreach ( ExpressionSyntax initializationExpression in initializerExpression . Expressions )
134
+ {
135
+ if ( semanticModel . GetOperation ( initializationExpression , token ) is not IOperation initializationOperation )
136
+ {
137
+ throw new ArgumentException ( "Failed to retrieve an operation for the current array element" ) ;
138
+ }
139
+
140
+ items . Add ( From ( initializationOperation , semanticModel , initializationExpression , token ) ) ;
141
+ }
142
+
143
+ return new Array ( elementTypeName , items . MoveToImmutable ( ) ) ;
114
144
}
115
145
116
146
throw new ArgumentException ( "Invalid attribute argument value" ) ;
0 commit comments