@@ -2121,8 +2121,7 @@ public async Task<int> GetTypeByName(string typeToSearch, CancellationToken toke
2121
2121
return retDebuggerCmdReader . ReadInt32 ( ) ;
2122
2122
}
2123
2123
2124
- // FIXME: support valuetypes
2125
- public async Task < GetMembersResult > GetValuesFromDebuggerProxyAttribute ( int objectId , int typeId , CancellationToken token )
2124
+ public async Task < GetMembersResult > GetValuesFromDebuggerProxyAttributeForObject ( int objectId , int typeId , CancellationToken token )
2126
2125
{
2127
2126
try
2128
2127
{
@@ -2132,25 +2131,11 @@ public async Task<GetMembersResult> GetValuesFromDebuggerProxyAttribute(int obje
2132
2131
2133
2132
using var ctorArgsWriter = new MonoBinaryWriter ( ) ;
2134
2133
ctorArgsWriter . Write ( ( byte ) ValueTypeId . Null ) ;
2135
-
2136
- // FIXME: move method invocation to valueTypeclass?
2137
- if ( ValueCreator . TryGetValueTypeById ( objectId , out var valueType ) )
2138
- {
2139
- //FIXME: Issue #68390
2140
- //ctorArgsWriter.Write((byte)0); //not used but needed
2141
- //ctorArgsWriter.Write(0); //not used but needed
2142
- //ctorArgsWriter.Write((int)1); // num args
2143
- //ctorArgsWriter.Write(valueType.Buffer);
2144
- return null ;
2145
- }
2146
- else
2147
- {
2148
- ctorArgsWriter . Write ( ( byte ) 0 ) ; //not used
2149
- ctorArgsWriter . Write ( 0 ) ; //not used
2150
- ctorArgsWriter . Write ( ( int ) 1 ) ; // num args
2151
- ctorArgsWriter . Write ( ( byte ) ElementType . Object ) ;
2152
- ctorArgsWriter . Write ( objectId ) ;
2153
- }
2134
+ ctorArgsWriter . Write ( ( byte ) 0 ) ; //not used
2135
+ ctorArgsWriter . Write ( 0 ) ; //not used
2136
+ ctorArgsWriter . Write ( ( int ) 1 ) ; // num args
2137
+ ctorArgsWriter . Write ( ( byte ) ElementType . Object ) ;
2138
+ ctorArgsWriter . Write ( objectId ) ;
2154
2139
2155
2140
var retMethod = await InvokeMethod ( ctorArgsWriter . GetParameterBuffer ( ) , methodId , token ) ;
2156
2141
if ( ! DotnetObjectId . TryParse ( retMethod ? [ "value" ] ? [ "objectId" ] ? . Value < string > ( ) , out DotnetObjectId dotnetObjectId ) )
@@ -2170,6 +2155,39 @@ public async Task<GetMembersResult> GetValuesFromDebuggerProxyAttribute(int obje
2170
2155
return null ;
2171
2156
}
2172
2157
2158
+ public async Task < GetMembersResult > GetValuesFromDebuggerProxyAttributeForValueTypes ( int valueTypeId , int typeId , CancellationToken token )
2159
+ {
2160
+ try
2161
+ {
2162
+ var typeName = await GetTypeName ( typeId , token ) ;
2163
+ int methodId = await FindDebuggerProxyConstructorIdFor ( typeId , token ) ;
2164
+ if ( methodId == - 1 )
2165
+ return null ;
2166
+
2167
+ using var ctorArgsWriter = new MonoBinaryWriter ( ) ;
2168
+ ctorArgsWriter . Write ( ( byte ) ValueTypeId . Null ) ;
2169
+
2170
+ if ( ! ValueCreator . TryGetValueTypeById ( valueTypeId , out var valueType ) )
2171
+ return null ;
2172
+ ctorArgsWriter . Write ( ( byte ) 0 ) ; //not used but needed
2173
+ ctorArgsWriter . Write ( 0 ) ; //not used but needed
2174
+ ctorArgsWriter . Write ( ( int ) 1 ) ; // num args
2175
+ ctorArgsWriter . Write ( valueType . Buffer ) ;
2176
+ var retMethod = await InvokeMethod ( ctorArgsWriter . GetParameterBuffer ( ) , methodId , token ) ;
2177
+ if ( ! DotnetObjectId . TryParse ( retMethod ? [ "value" ] ? [ "objectId" ] ? . Value < string > ( ) , out DotnetObjectId dotnetObjectId ) )
2178
+ throw new Exception ( $ "Invoking .ctor ({ methodId } ) for DebuggerTypeProxy on type { typeId } returned { retMethod } ") ;
2179
+ GetMembersResult members = await GetTypeMemberValues ( dotnetObjectId ,
2180
+ GetObjectCommandOptions . WithProperties | GetObjectCommandOptions . ForDebuggerProxyAttribute ,
2181
+ token ) ;
2182
+ return members ;
2183
+ }
2184
+ catch ( Exception e )
2185
+ {
2186
+ logger . LogDebug ( $ "Could not evaluate DebuggerTypeProxyAttribute of type { await GetTypeName ( typeId , token ) } - { e } ") ;
2187
+ return null ;
2188
+ }
2189
+ }
2190
+
2173
2191
private async Task < int > FindDebuggerProxyConstructorIdFor ( int typeId , CancellationToken token )
2174
2192
{
2175
2193
try
@@ -2178,59 +2196,79 @@ private async Task<int> FindDebuggerProxyConstructorIdFor(int typeId, Cancellati
2178
2196
if ( getCAttrsRetReader == null )
2179
2197
return - 1 ;
2180
2198
2181
- var methodId = - 1 ;
2182
2199
var parmCount = getCAttrsRetReader . ReadInt32 ( ) ;
2183
- for ( int j = 0 ; j < parmCount ; j ++ )
2200
+ if ( parmCount != 1 )
2201
+ throw new InternalErrorException ( $ "Expected to find custom attribute with only one argument, but it has { parmCount } parameters.") ;
2202
+
2203
+ byte monoParamTypeId = getCAttrsRetReader . ReadByte ( ) ;
2204
+ // FIXME: DebuggerTypeProxyAttribute(string) - not supported
2205
+ if ( ( ValueTypeId ) monoParamTypeId != ValueTypeId . Type )
2184
2206
{
2185
- var monoTypeId = getCAttrsRetReader . ReadByte ( ) ;
2186
- // FIXME: DebuggerTypeProxyAttribute(string) - not supported
2187
- if ( ( ValueTypeId ) monoTypeId != ValueTypeId . Type )
2188
- continue ;
2207
+ logger . LogDebug ( $ "DebuggerTypeProxy attribute is only supported with a System.Type parameter type. Got { ( ValueTypeId ) monoParamTypeId } ") ;
2208
+ return - 1 ;
2209
+ }
2210
+
2211
+ var typeProxyTypeId = getCAttrsRetReader . ReadInt32 ( ) ;
2212
+
2213
+ using var commandParamsWriter = new MonoBinaryWriter ( ) ;
2214
+ commandParamsWriter . Write ( typeProxyTypeId ) ;
2215
+ var originalClassName = await GetTypeNameOriginal ( typeProxyTypeId , token ) ;
2189
2216
2190
- var cAttrTypeId = getCAttrsRetReader . ReadInt32 ( ) ;
2191
- using var commandParamsWriter = new MonoBinaryWriter ( ) ;
2192
- commandParamsWriter . Write ( cAttrTypeId ) ;
2193
- var className = await GetTypeNameOriginal ( cAttrTypeId , token ) ;
2194
- if ( className . IndexOf ( '[' ) > 0 )
2217
+ if ( originalClassName . IndexOf ( '[' ) > 0 )
2218
+ {
2219
+ string className = originalClassName ;
2220
+ className = className . Remove ( className . IndexOf ( '[' ) ) ;
2221
+ var assemblyId = await GetAssemblyIdFromType ( typeProxyTypeId , token ) ;
2222
+ var assemblyName = await GetFullAssemblyName ( assemblyId , token ) ;
2223
+
2224
+ StringBuilder typeToSearch = new ( className ) ;
2225
+ typeToSearch . Append ( '[' ) ;
2226
+ List < int > genericTypeArgs = await GetTypeParamsOrArgsForGenericType ( typeId , token ) ;
2227
+ for ( int k = 0 ; k < genericTypeArgs . Count ; k ++ )
2195
2228
{
2196
- className = className . Remove ( className . IndexOf ( '[' ) ) ;
2197
- var assemblyId = await GetAssemblyIdFromType ( cAttrTypeId , token ) ;
2198
- var assemblyName = await GetFullAssemblyName ( assemblyId , token ) ;
2199
- var typeToSearch = className ;
2200
- typeToSearch += "[[" ; //System.Collections.Generic.List`1[[System.Int32,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089]],mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
2201
- List < int > genericTypeArgs = await GetTypeParamsOrArgsForGenericType ( typeId , token ) ;
2202
- for ( int k = 0 ; k < genericTypeArgs . Count ; k ++ )
2203
- {
2204
- var assemblyIdArg = await GetAssemblyIdFromType ( genericTypeArgs [ k ] , token ) ;
2205
- var assemblyNameArg = await GetFullAssemblyName ( assemblyIdArg , token ) ;
2206
- var classNameArg = await GetTypeNameOriginal ( genericTypeArgs [ k ] , token ) ;
2207
- typeToSearch += classNameArg + ", " + assemblyNameArg ;
2208
- if ( k + 1 < genericTypeArgs . Count )
2209
- typeToSearch += "], [" ;
2210
- else
2211
- typeToSearch += "]" ;
2212
- }
2213
- typeToSearch += "]" ;
2214
- typeToSearch += ", " + assemblyName ;
2215
- var genericTypeId = await GetTypeByName ( typeToSearch , token ) ;
2216
- if ( genericTypeId < 0 )
2217
- break ;
2218
- cAttrTypeId = genericTypeId ;
2229
+ // typeToSearch += '[';
2230
+ var assemblyIdArg = await GetAssemblyIdFromType ( genericTypeArgs [ k ] , token ) ;
2231
+ var assemblyNameArg = await GetFullAssemblyName ( assemblyIdArg , token ) ;
2232
+ var classNameArg = await GetTypeNameOriginal ( genericTypeArgs [ k ] , token ) ;
2233
+ typeToSearch . Append ( $ "{ ( k == 0 ? "" : "," ) } [{ classNameArg } , { assemblyNameArg } ]") ;
2219
2234
}
2220
- int [ ] methodIds = await GetMethodIdsByName ( cAttrTypeId , ".ctor" , BindingFlags . Default , token ) ;
2221
- if ( methodIds != null )
2222
- methodId = methodIds [ 0 ] ;
2223
- break ;
2235
+ typeToSearch . Append ( $ "], { assemblyName } ") ;
2236
+ var genericTypeId = await GetTypeByName ( typeToSearch . ToString ( ) , token ) ;
2237
+ if ( genericTypeId < 0 )
2238
+ {
2239
+ logger . LogDebug ( $ "Could not find instantiated generic type id for { typeToSearch } .") ;
2240
+ return - 1 ;
2241
+ }
2242
+ typeProxyTypeId = genericTypeId ;
2224
2243
}
2244
+ int [ ] constructorIds = await GetMethodIdsByName ( typeProxyTypeId , ".ctor" , BindingFlags . DeclaredOnly , token ) ;
2245
+ if ( constructorIds is null )
2246
+ throw new InternalErrorException ( $ "Could not find any constructor for DebuggerProxy type: { originalClassName } ") ;
2247
+
2248
+ if ( constructorIds . Length == 1 )
2249
+ return constructorIds [ 0 ] ;
2225
2250
2226
- return methodId ;
2251
+ string expectedConstructorParamType = await GetTypeName ( typeId , token ) ;
2252
+ foreach ( var methodId in constructorIds )
2253
+ {
2254
+ var methodInfoFromRuntime = await GetMethodInfo ( methodId , token ) ;
2255
+ // avoid calling to runtime if possible
2256
+ var ps = methodInfoFromRuntime . Info . GetParametersInfo ( ) ;
2257
+ if ( ps . Length != 1 )
2258
+ continue ;
2259
+ string parameters = await GetParameters ( methodId , token ) ;
2260
+ if ( string . IsNullOrEmpty ( parameters ) )
2261
+ throw new InternalErrorException ( $ "Could not get method's parameter types. MethodId = { methodId } .") ;
2262
+ if ( parameters == $ "({ expectedConstructorParamType } )")
2263
+ return methodId ;
2264
+ }
2265
+ throw new InternalErrorException ( $ "Could not find a matching constructor for DebuggerProxy type: { originalClassName } ") ;
2227
2266
}
2228
2267
catch ( Exception e )
2229
2268
{
2230
2269
logger . LogDebug ( $ "Could not evaluate DebuggerTypeProxyAttribute of type { await GetTypeName ( typeId , token ) } - { e } ") ;
2270
+ return - 1 ;
2231
2271
}
2232
-
2233
- return - 1 ;
2234
2272
}
2235
2273
2236
2274
public ValueTypeClass GetValueTypeClass ( int valueTypeId )
0 commit comments