@ -20,6 +20,7 @@ using System;
@@ -20,6 +20,7 @@ using System;
using System.Collections.Generic ;
using System.Collections.Immutable ;
using System.Diagnostics ;
using System.Diagnostics.CodeAnalysis ;
using System.Linq ;
using System.Text ;
@ -32,6 +33,8 @@ using ICSharpCode.Decompiler.TypeSystem;
@@ -32,6 +33,8 @@ using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation ;
using ICSharpCode.Decompiler.Util ;
# nullable enable
namespace ICSharpCode.Decompiler.CSharp
{
struct CallBuilder
@ -47,10 +50,10 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -47,10 +50,10 @@ namespace ICSharpCode.Decompiler.CSharp
public TranslatedExpression [ ] Arguments ;
public IParameter [ ] ExpectedParameters ;
public string [ ] ParameterNames ;
public string [ ] ArgumentNames ;
public string [ ] ? ArgumentNames ;
public int FirstOptionalArgumentIndex ;
public BitSet IsPrimitiveValue ;
public IReadOnlyList < int > ArgumentToParameterMap ;
public IReadOnlyList < int > ? ArgumentToParameterMap ;
public bool AddNamesToPrimitiveValues ;
public bool UseImplicitlyTypedOut ;
@ -64,9 +67,9 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -64,9 +67,9 @@ namespace ICSharpCode.Decompiler.CSharp
return FirstOptionalArgumentIndex ;
}
public string [ ] GetArgumentNames ( int skipCount = 0 )
public string [ ] ? GetArgumentNames ( int skipCount = 0 )
{
string [ ] argumentNames = ArgumentNames ;
string [ ] ? argumentNames = ArgumentNames ;
if ( AddNamesToPrimitiveValues & & IsPrimitiveValue . Any ( ) & & ! IsExpandedForm
& & ! ParameterNames . Any ( string . IsNullOrEmpty ) )
{
@ -154,7 +157,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -154,7 +157,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
for ( int i = 0 ; i < Arguments . Length ; i + + )
{
string inferredName ;
string? inferredName ;
switch ( Arguments [ i ] . Expression )
{
case IdentifierExpression identifier :
@ -196,7 +199,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -196,7 +199,7 @@ namespace ICSharpCode.Decompiler.CSharp
this . typeSystem = typeSystem ;
}
public TranslatedExpression Build ( CallInstruction inst , IType typeHint = null )
public TranslatedExpression Build ( CallInstruction inst , IType ? typeHint = null )
{
if ( inst is NewObj newobj & & IL . Transforms . DelegateConstruction . MatchDelegateConstruction ( newobj , out _ , out _ , out _ ) )
{
@ -255,7 +258,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -255,7 +258,7 @@ namespace ICSharpCode.Decompiler.CSharp
return result ;
}
static bool IsSpanBasedStringConcat ( CallInstruction call , out List < ( ILInstruction , KnownTypeCode ) > operands )
static bool IsSpanBasedStringConcat ( CallInstruction call , [ NotNullWhen ( true ) ] out List < ( ILInstruction , KnownTypeCode ) > ? operands )
{
operands = null ;
@ -321,8 +324,8 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -321,8 +324,8 @@ namespace ICSharpCode.Decompiler.CSharp
public ExpressionWithResolveResult Build ( OpCode callOpCode , IMethod method ,
IReadOnlyList < ILInstruction > callArguments ,
IReadOnlyList < int > argumentToParameterMap = null ,
IType constrainedTo = null )
IReadOnlyList < int > ? argumentToParameterMap = null ,
IType ? constrainedTo = null )
{
if ( method . IsExplicitInterfaceImplementation & & callOpCode = = OpCode . Call )
{
@ -340,7 +343,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -340,7 +343,7 @@ namespace ICSharpCode.Decompiler.CSharp
var expectedTargetDetails = new ExpectedTargetDetails {
CallOpCode = callOpCode
} ;
ILFunction localFunction = null ;
ILFunction ? localFunction = null ;
if ( method . IsLocalFunction )
{
localFunction = expressionBuilder . ResolveLocalFunction ( method ) ;
@ -353,7 +356,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -353,7 +356,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
else if ( localFunction ! = null )
{
var ide = new IdentifierExpression ( localFunction . Name ) ;
var ide = new IdentifierExpression ( localFunction . Name ! ) ;
if ( method . TypeArguments . Count > 0 )
{
ide . TypeArguments . AddRange ( method . TypeArguments . Select ( expressionBuilder . ConvertType ) ) ;
@ -522,13 +525,15 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -522,13 +525,15 @@ namespace ICSharpCode.Decompiler.CSharp
}
var transform = GetRequiredTransformationsForCall ( expectedTargetDetails , method , ref target ,
ref argumentList , CallTransformation . All , out IParameterizedMember foundMethod ) ;
ref argumentList , CallTransformation . All , out IParameterizedMember ? foundMethod ) ;
// GetRequiredTransformationsForCall always assigns foundMethod (the resolved overload or 'method').
Debug . Assert ( foundMethod ! = null ) ;
// Note: after this, 'method' and 'foundMethod' may differ,
// but as far as allowed by IsAppropriateCallTarget().
// Need to update list of parameter names, because foundMethod is different and thus might use different names.
if ( ! method . Equals ( foundMethod ) & & argumentList . ParameterNames . Length > = foundMethod . Parameters . Count )
if ( ! method . Equals ( foundMethod ) & & argumentList . ParameterNames . Length > = foundMethod ! . Parameters . Count )
{
for ( int i = 0 ; i < foundMethod . Parameters . Count ; i + + )
{
@ -582,7 +587,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -582,7 +587,7 @@ namespace ICSharpCode.Decompiler.CSharp
private ExpressionWithResolveResult HandleStringInterpolation ( IMethod method , ArgumentList argumentList )
{
if ( ! TryGetStringInterpolationTokens ( argumentList , out string format , out var tokens ) )
if ( ! TryGetStringInterpolationTokens ( argumentList , out string? format , out var tokens ) )
return default ;
var arguments = argumentList . Arguments ;
@ -598,7 +603,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -598,7 +603,7 @@ namespace ICSharpCode.Decompiler.CSharp
return ;
var arrayCreation = ( ArrayCreateExpression ) argumentList . Arguments [ 1 ] . Expression ;
var arrayCreationRR = ( ArrayCreateResolveResult ) argumentList . Arguments [ 1 ] . ResolveResult ;
var element = arrayCreation . Initializer . Elements . First ( ) . Detach ( ) ;
var element = arrayCreation . Initializer ! . Elements . First ( ) . Detach ( ) ;
argument = new TranslatedExpression ( element , arrayCreationRR . InitializerElements . First ( ) ) ;
}
@ -714,7 +719,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -714,7 +719,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
public ExpressionWithResolveResult BuildDictionaryInitializerExpression ( OpCode callOpCode , IMethod method ,
InitializedObjectResolveResult target , IReadOnlyList < ILInstruction > indices , ILInstruction value = null )
InitializedObjectResolveResult target , IReadOnlyList < ILInstruction > indices , ILInstruction ? value = null )
{
if ( method is null )
throw new ArgumentNullException ( nameof ( method ) ) ;
@ -755,7 +760,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -755,7 +760,7 @@ namespace ICSharpCode.Decompiler.CSharp
) ;
}
private bool TryGetStringInterpolationTokens ( ArgumentList argumentList , out string format , out List < ( TokenKind Kind , int Index , int Alignment , string Format ) > tokens )
private bool TryGetStringInterpolationTokens ( ArgumentList argumentList , [ NotNullWhen ( true ) ] out string? format , [ NotNullWhen ( true ) ] out List < ( TokenKind Kind , int Index , int Alignment , string? Format ) > ? tokens )
{
tokens = null ;
format = null ;
@ -766,9 +771,9 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -766,9 +771,9 @@ namespace ICSharpCode.Decompiler.CSharp
return false ;
if ( ! arguments . Skip ( 1 ) . All ( a = > ! a . Expression . DescendantsAndSelf . OfType < PrimitiveExpression > ( ) . Any ( p = > p . Value is string ) ) )
return false ;
tokens = new List < ( TokenKind Kind , int Index , int Alignment , string Format ) > ( ) ;
tokens = new List < ( TokenKind Kind , int Index , int Alignment , string? Format ) > ( ) ;
int i = 0 ;
format = ( string ) crr . ConstantValue ;
format = ( string ) crr . ConstantValue ! ;
foreach ( var ( kind , data ) in TokenizeFormatString ( format ) )
{
int index ;
@ -787,7 +792,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -787,7 +792,7 @@ namespace ICSharpCode.Decompiler.CSharp
tokens . Add ( ( kind , index , 0 , null ) ) ;
break ;
case TokenKind . ArgumentWithFormat :
arg = data . Split ( new [ ] { ':' } , 2 ) ;
arg = data ! . Split ( new [ ] { ':' } , 2 ) ;
if ( arg . Length ! = 2 | | arg [ 1 ] . Length = = 0 )
return false ;
if ( ! int . TryParse ( arg [ 0 ] , out index ) | | index ! = i )
@ -796,7 +801,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -796,7 +801,7 @@ namespace ICSharpCode.Decompiler.CSharp
tokens . Add ( ( kind , index , 0 , arg [ 1 ] ) ) ;
break ;
case TokenKind . ArgumentWithAlignment :
arg = data . Split ( new [ ] { ',' } , 2 ) ;
arg = data ! . Split ( new [ ] { ',' } , 2 ) ;
if ( arg . Length ! = 2 | | arg [ 1 ] . Length = = 0 )
return false ;
if ( ! int . TryParse ( arg [ 0 ] , out index ) | | index ! = i )
@ -807,7 +812,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -807,7 +812,7 @@ namespace ICSharpCode.Decompiler.CSharp
tokens . Add ( ( kind , index , alignment , null ) ) ;
break ;
case TokenKind . ArgumentWithAlignmentAndFormat :
arg = data . Split ( new [ ] { ',' , ':' } , 3 ) ;
arg = data ! . Split ( new [ ] { ',' , ':' } , 3 ) ;
if ( arg . Length ! = 3 | | arg [ 1 ] . Length = = 0 | | arg [ 2 ] . Length = = 0 )
return false ;
if ( ! int . TryParse ( arg [ 0 ] , out index ) | | index ! = i )
@ -834,7 +839,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -834,7 +839,7 @@ namespace ICSharpCode.Decompiler.CSharp
ArgumentWithAlignmentAndFormat ,
}
private IEnumerable < ( TokenKind , string ) > TokenizeFormatString ( string value )
private IEnumerable < ( TokenKind , string? ) > TokenizeFormatString ( string value )
{
int pos = - 1 ;
@ -926,14 +931,14 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -926,14 +931,14 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
private ArgumentList BuildArgumentList ( ExpectedTargetDetails expectedTargetDetails , ResolveResult target , IMethod method ,
int firstParamIndex , IReadOnlyList < ILInstruction > callArguments , IReadOnlyList < int > argumentToParameterMap )
private ArgumentList BuildArgumentList ( ExpectedTargetDetails expectedTargetDetails , ResolveResult ? target , IMethod method ,
int firstParamIndex , IReadOnlyList < ILInstruction > callArguments , IReadOnlyList < int > ? argumentToParameterMap )
{
ArgumentList list = new ArgumentList ( ) ;
// Translate arguments to the expected parameter types
var arguments = new List < TranslatedExpression > ( method . Parameters . Count ) ;
string [ ] argumentNames = null ;
string [ ] ? argumentNames = null ;
Debug . Assert ( callArguments . Count = = firstParamIndex + method . Parameters . Count ) ;
var expectedParameters = new List < IParameter > ( method . Parameters . Count ) ; // parameters, but in argument order
bool isExpandedForm = false ;
@ -1038,12 +1043,12 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1038,12 +1043,12 @@ namespace ICSharpCode.Decompiler.CSharp
return p . Type . IsKnownType ( KnownTypeCode . Boolean ) ;
}
private bool TransformParamsArgument ( ExpectedTargetDetails expectedTargetDetails , ResolveResult targetResolveResult ,
private bool TransformParamsArgument ( ExpectedTargetDetails expectedTargetDetails , ResolveResult ? targetResolveResult ,
IMethod method , IParameter parameter , TranslatedExpression paramsArgument , ref List < IParameter > expectedParameters ,
ref List < TranslatedExpression > arguments )
{
var expressionBuilder = this . expressionBuilder ;
if ( ExtractArguments ( out IType elementType , out var expandedParameters , out var expandedArguments ) )
if ( ExtractArguments ( out var elementType , out var expandedParameters , out var expandedArguments ) )
{
expandedParameters . InsertRange ( 0 , expectedParameters ) ;
expandedArguments . InsertRange ( 0 , arguments ) ;
@ -1059,7 +1064,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1059,7 +1064,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
return false ;
bool ExtractArguments ( out IType elementType , out List < IParameter > parameters , out List < TranslatedExpression > arguments )
bool ExtractArguments ( [ NotNullWhen ( true ) ] out IType ? elementType , [ NotNullWhen ( true ) ] out List < IParameter > ? parameters , [ NotNullWhen ( true ) ] out List < TranslatedExpression > ? arguments )
{
elementType = null ;
parameters = null ;
@ -1138,13 +1143,13 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1138,13 +1143,13 @@ namespace ICSharpCode.Decompiler.CSharp
}
private CallTransformation GetRequiredTransformationsForCall ( ExpectedTargetDetails expectedTargetDetails , IMethod method ,
ref TranslatedExpression target , ref ArgumentList argumentList , CallTransformation allowedTransforms , out IParameterizedMember foundMethod )
ref TranslatedExpression target , ref ArgumentList argumentList , CallTransformation allowedTransforms , out IParameterizedMember ? foundMethod )
{
CallTransformation transform = CallTransformation . None ;
// initialize requireTarget flag
bool requireTarget ;
ResolveResult targetResolveResult ;
ResolveResult ? targetResolveResult ;
if ( ( allowedTransforms & CallTransformation . RequireTarget ) ! = 0 )
{
if ( settings . AlwaysQualifyMemberReferences | | expressionBuilder . HidesVariableWithName ( method . Name ) )
@ -1475,9 +1480,9 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1475,9 +1480,9 @@ namespace ICSharpCode.Decompiler.CSharp
}
OverloadResolutionErrors IsUnambiguousCall ( ExpectedTargetDetails expectedTargetDetails , IMethod method ,
ResolveResult target , IType [ ] typeArguments , ResolveResult [ ] arguments ,
string [ ] argumentNames , int firstOptionalArgumentIndex ,
out IParameterizedMember foundMember , out bool bestCandidateIsExpandedForm )
ResolveResult ? target , IType [ ] typeArguments , ResolveResult [ ] arguments ,
string [ ] ? argumentNames , int firstOptionalArgumentIndex ,
out IParameterizedMember ? foundMember , out bool bestCandidateIsExpandedForm )
{
foundMember = null ;
bestCandidateIsExpandedForm = false ;
@ -1585,8 +1590,8 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1585,8 +1590,8 @@ namespace ICSharpCode.Decompiler.CSharp
return OverloadResolutionErrors . None ;
}
bool IsUnambiguousAccess ( ExpectedTargetDetails expectedTargetDetails , ResolveResult target , IMethod method ,
IList < TranslatedExpression > arguments , string [ ] argumentNames , out IMember foundMember )
bool IsUnambiguousAccess ( ExpectedTargetDetails expectedTargetDetails , ResolveResult ? target , IMethod method ,
IList < TranslatedExpression > arguments , string [ ] ? argumentNames , [ NotNullWhen ( true ) ] out IMember ? foundMember )
{
Log . WriteLine ( "IsUnambiguousAccess: Performing overload resolution for " + method ) ;
Log . WriteCollection ( " Arguments: " , arguments . Select ( a = > a . ResolveResult ) ) ;
@ -1594,7 +1599,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1594,7 +1599,7 @@ namespace ICSharpCode.Decompiler.CSharp
foundMember = null ;
if ( target = = null )
{
var result = resolver . ResolveSimpleName ( method . AccessorOwner . Name ,
var result = resolver . ResolveSimpleName ( method . AccessorOwner ! . Name ,
EmptyList < IType > . Instance ,
isInvocationTarget : false ) as MemberResolveResult ;
if ( result = = null | | result . IsError )
@ -1604,7 +1609,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1604,7 +1609,7 @@ namespace ICSharpCode.Decompiler.CSharp
else
{
var lookup = new MemberLookup ( resolver . CurrentTypeDefinition , resolver . CurrentTypeDefinition . ParentModule ) ;
if ( method . AccessorOwner . SymbolKind = = SymbolKind . Indexer )
if ( method . AccessorOwner ! . SymbolKind = = SymbolKind . Indexer )
{
var or = new OverloadResolution ( resolver . Compilation ,
arguments . SelectArray ( a = > a . ResolveResult ) ,
@ -1621,7 +1626,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1621,7 +1626,7 @@ namespace ICSharpCode.Decompiler.CSharp
else
{
var result = lookup . Lookup ( target ,
method . AccessorOwner . Name ,
method . AccessorOwner ! . Name ,
EmptyList < IType > . Instance ,
isInvocation : false ) as MemberResolveResult ;
if ( result = = null | | result . IsError )
@ -1633,10 +1638,10 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1633,10 +1638,10 @@ namespace ICSharpCode.Decompiler.CSharp
}
ExpressionWithResolveResult HandleAccessorCall ( ExpectedTargetDetails expectedTargetDetails , IMethod method ,
TranslatedExpression target , List < TranslatedExpression > arguments , string [ ] argumentNames )
TranslatedExpression target , List < TranslatedExpression > arguments , string [ ] ? argumentNames )
{
bool requireTarget ;
if ( settings . AlwaysQualifyMemberReferences | | method . AccessorOwner . SymbolKind = = SymbolKind . Indexer | | expressionBuilder . HidesVariableWithName ( method . AccessorOwner . Name ) )
if ( settings . AlwaysQualifyMemberReferences | | method . AccessorOwner ! . SymbolKind = = SymbolKind . Indexer | | expressionBuilder . HidesVariableWithName ( method . AccessorOwner . Name ) )
requireTarget = true ;
else if ( method . IsStatic )
requireTarget = ! expressionBuilder . IsCurrentOrContainingType ( method . DeclaringTypeDefinition ) ;
@ -1654,7 +1659,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1654,7 +1659,7 @@ namespace ICSharpCode.Decompiler.CSharp
arguments . Remove ( value ) ;
}
IMember foundMember ;
IMember ? foundMember ;
while ( ! IsUnambiguousAccess ( expectedTargetDetails , targetResolveResult , method , arguments , argumentNames , out foundMember ) )
{
if ( ! argumentsCasted )
@ -1670,12 +1675,12 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1670,12 +1675,12 @@ namespace ICSharpCode.Decompiler.CSharp
else if ( ! targetCasted )
{
targetCasted = true ;
target = target . ConvertTo ( method . AccessorOwner . DeclaringType , expressionBuilder ) ;
target = target . ConvertTo ( method . AccessorOwner ! . DeclaringType , expressionBuilder ) ;
targetResolveResult = target . ResolveResult ;
}
else
{
foundMember = method . AccessorOwner ;
foundMember = method . AccessorOwner ! ;
break ;
}
}
@ -1693,12 +1698,12 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1693,12 +1698,12 @@ namespace ICSharpCode.Decompiler.CSharp
}
else if ( requireTarget )
{
expr = new MemberReferenceExpression ( target . Expression , method . AccessorOwner . Name )
expr = new MemberReferenceExpression ( target . Expression , method . AccessorOwner ! . Name )
. WithoutILInstruction ( ) . WithRR ( rr ) ;
}
else
{
expr = new IdentifierExpression ( method . AccessorOwner . Name )
expr = new IdentifierExpression ( method . AccessorOwner ! . Name )
. WithoutILInstruction ( ) . WithRR ( rr ) ;
}
@ -1714,7 +1719,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1714,7 +1719,7 @@ namespace ICSharpCode.Decompiler.CSharp
op = AssignmentOperatorType . Subtract ;
}
}
return new AssignmentExpression ( expr , op , value . Expression ) . WithRR ( new TypeResolveResult ( method . AccessorOwner . ReturnType ) ) ;
return new AssignmentExpression ( expr , op , value . Expression ! ) . WithRR ( new TypeResolveResult ( method . AccessorOwner ! . ReturnType ) ) ;
}
else
{
@ -1725,12 +1730,12 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1725,12 +1730,12 @@ namespace ICSharpCode.Decompiler.CSharp
}
else if ( requireTarget )
{
return new MemberReferenceExpression ( target . Expression , method . AccessorOwner . Name )
return new MemberReferenceExpression ( target . Expression , method . AccessorOwner ! . Name )
. WithoutILInstruction ( ) . WithRR ( rr ) ;
}
else
{
return new IdentifierExpression ( method . AccessorOwner . Name )
return new IdentifierExpression ( method . AccessorOwner ! . Name )
. WithoutILInstruction ( ) . WithRR ( rr ) ;
}
}
@ -1756,7 +1761,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1756,7 +1761,7 @@ namespace ICSharpCode.Decompiler.CSharp
return false ;
}
ExpressionWithResolveResult HandleConstructorCall ( ExpectedTargetDetails expectedTargetDetails , ResolveResult target , IMethod method , ArgumentList argumentList )
ExpressionWithResolveResult HandleConstructorCall ( ExpectedTargetDetails expectedTargetDetails , ResolveResult ? target , IMethod method , ArgumentList argumentList )
{
if ( settings . AnonymousTypes & & method . DeclaringType . IsAnonymousType ( ) )
{
@ -1802,7 +1807,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1802,7 +1807,7 @@ namespace ICSharpCode.Decompiler.CSharp
CastArguments ( argumentList . Arguments , argumentList . ExpectedParameters ) ;
break ; // make sure that we don't not end up in an infinite loop
}
IType returnTypeOverride = null ;
IType ? returnTypeOverride = null ;
if ( typeSystem . MainModule . TypeSystemOptions . HasFlag ( TypeSystemOptions . NativeIntegersWithoutAttribute ) )
{
// For DeclaringType, we don't use nint/nuint (so that DeclaringType.GetConstructors etc. works),
@ -1908,7 +1913,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1908,7 +1913,7 @@ namespace ICSharpCode.Decompiler.CSharp
return expr . Expression . WithRR ( new MemberResolveResult ( null , method ) ) ;
}
ExpressionWithResolveResult BuildDelegateReference ( IMethod method , IMethod invokeMethod , ExpectedTargetDetails expectedTargetDetails , ILInstruction thisArg )
ExpressionWithResolveResult BuildDelegateReference ( IMethod method , IMethod ? invokeMethod , ExpectedTargetDetails expectedTargetDetails , ILInstruction ? thisArg )
{
ExpressionBuilder expressionBuilder = this . expressionBuilder ;
ExpressionWithResolveResult targetExpression ;
@ -1935,13 +1940,13 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1935,13 +1940,13 @@ namespace ICSharpCode.Decompiler.CSharp
}
( TranslatedExpression target , bool addTypeArguments , string methodName , ResolveResult result ) DisambiguateDelegateReference ( IMethod method , IMethod invokeMethod , ExpectedTargetDetails expectedTargetDetails , ILInstruction thisArg )
( TranslatedExpression target , bool addTypeArguments , string methodName , ResolveResult result ) DisambiguateDelegateReference ( IMethod method , IMethod ? invokeMethod , ExpectedTargetDetails expectedTargetDetails , ILInstruction ? thisArg )
{
if ( method . IsLocalFunction )
{
ILFunction localFunction = expressionBuilder . ResolveLocalFunction ( method ) ;
ILFunction ? localFunction = expressionBuilder . ResolveLocalFunction ( method ) ;
Debug . Assert ( localFunction ! = null ) ;
return ( default , addTypeArguments : true , localFunction . Name , ToMethodGroup ( method , localFunction ) ) ;
return ( default , addTypeArguments : true , localFunction . Name ! , ToMethodGroup ( method , localFunction ) ) ;
}
if ( method . IsExtensionMethod & & method . Parameters . Count - 1 = = invokeMethod ? . Parameters . Count )
{
@ -1951,21 +1956,21 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1951,21 +1956,21 @@ namespace ICSharpCode.Decompiler.CSharp
targetType = ( ( ByReferenceType ) targetType ) . ElementType ;
thisArg = thisArgBox . Argument ;
}
TranslatedExpression target = expressionBuilder . Translate ( thisArg , targetType ) ;
TranslatedExpression target = expressionBuilder . Translate ( thisArg ! , targetType ) ;
var currentTarget = target ;
bool targetCasted = false ;
bool addTypeArguments = false ;
// Initial inputs for IsUnambiguousMethodReference:
ResolveResult targetResolveResult = target . ResolveResult ;
IReadOnlyList < IType > typeArguments = EmptyList < IType > . Instance ;
if ( thisArg . MatchLdNull ( ) )
if ( thisArg ! . MatchLdNull ( ) )
{
targetCasted = true ;
currentTarget = currentTarget . ConvertTo ( targetType , expressionBuilder ) ;
targetResolveResult = currentTarget . ResolveResult ;
}
// Find somewhat minimal solution:
ResolveResult result ;
ResolveResult ? result ;
while ( ! IsUnambiguousMethodReference ( expectedTargetDetails , method , targetResolveResult , typeArguments , true , out result ) )
{
if ( ! targetCasted )
@ -1985,7 +1990,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -1985,7 +1990,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
break ;
}
return ( currentTarget , addTypeArguments , method . Name , result ) ;
return ( currentTarget , addTypeArguments , method . Name , result ! ) ;
}
else
{
@ -2019,10 +2024,10 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -2019,10 +2024,10 @@ namespace ICSharpCode.Decompiler.CSharp
bool targetCasted = false ;
bool addTypeArguments = false ;
// Initial inputs for IsUnambiguousMethodReference:
ResolveResult targetResolveResult = targetAdded ? target . ResolveResult : null ;
ResolveResult ? targetResolveResult = targetAdded ? target . ResolveResult : null ;
IReadOnlyList < IType > typeArguments = EmptyList < IType > . Instance ;
// Find somewhat minimal solution:
ResolveResult result ;
ResolveResult ? result ;
while ( ! IsUnambiguousMethodReference ( expectedTargetDetails , method , targetResolveResult , typeArguments , false , out result ) )
{
if ( ! addTypeArguments )
@ -2054,7 +2059,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -2054,7 +2059,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
result = mgrr . WithChosenMethod ( method ) ;
}
return ( currentTarget , addTypeArguments , method . Name , result ) ;
return ( currentTarget , addTypeArguments , method . Name , result ! ) ;
}
}
@ -2071,7 +2076,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -2071,7 +2076,7 @@ namespace ICSharpCode.Decompiler.CSharp
return oce ;
}
bool IsUnambiguousMethodReference ( ExpectedTargetDetails expectedTargetDetails , IMethod method , ResolveResult target , IReadOnlyList < IType > typeArguments , bool isExtensionMethodReference , out ResolveResult result )
bool IsUnambiguousMethodReference ( ExpectedTargetDetails expectedTargetDetails , IMethod method , ResolveResult ? target , IReadOnlyList < IType > typeArguments , bool isExtensionMethodReference , [ NotNullWhen ( true ) ] out ResolveResult ? result )
{
Log . WriteLine ( "IsUnambiguousMethodReference: Performing overload resolution for " + method ) ;