/// <summary> /// Collect all the available cast pairs, format is (target argument expression, potential conversion type) /// </summary> /// <param name="targetArgument"> The argument that need to be cast</param> /// <param name="argumentList"> The argument list that contains the target argument to be cast </param> /// <param name="invocationNode"> The invocation node that is the parent of "argumentList"</param> /// <returns> /// Return all the available cast pairs, format is (target argument expression, potential conversion type) /// </returns> public ImmutableArray <(TExpressionSyntax, ITypeSymbol)> GetPotentialConversionTypes( SemanticModel semanticModel, SyntaxNode root, TArgumentSyntax targetArgument, TArgumentListSyntax argumentList, TInvocationSyntax invocationNode, CancellationToken cancellationToken ) { // Implicit downcast appears on the argument of invocation node, // get all candidate functions and extract potential conversion types var symbolInfo = semanticModel.GetSymbolInfo(invocationNode, cancellationToken); using var _ = ArrayBuilder <ISymbol> .GetInstance(out var candidateSymbols); if (symbolInfo.Symbol != null) // BC42016: the only candidate symbol is symbolInfo.Symbol { candidateSymbols.Add(symbolInfo.Symbol); } else { candidateSymbols.AddRange(symbolInfo.CandidateSymbols); } using var __ = ArrayBuilder <(TExpressionSyntax, ITypeSymbol)> .GetInstance( out var mutablePotentialConversionTypes ); foreach (var candidateSymbol in candidateSymbols.OfType <IMethodSymbol>()) { if ( CanArgumentTypesBeConvertedToParameterTypes( semanticModel, root, argumentList, candidateSymbol.Parameters, targetArgument, cancellationToken, out var targetArgumentConversionType ) && GetExpressionOfArgument(targetArgument) is TExpressionSyntax argumentExpression ) { mutablePotentialConversionTypes.Add( (argumentExpression, targetArgumentConversionType) ); } } // Sort the potential conversion types by inheritance distance, so that // operations are in order and user can choose least specific types(more accurate) mutablePotentialConversionTypes.Sort( new InheritanceDistanceComparer <TExpressionSyntax>(semanticModel) ); return(mutablePotentialConversionTypes.ToImmutable()); }
protected abstract SyntaxNode GetExpression(TInvocationSyntax memberAccess);
protected abstract bool HasNumberOfArguments(TInvocationSyntax invocation, int number);
// this will return null if there's no argument in the invocation // the check must be done beforehand protected abstract SyntaxNode GetFirstArgument(TInvocationSyntax invocation);