Beispiel #1
0
            /// <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());
            }
Beispiel #2
0
 protected abstract SyntaxNode GetExpression(TInvocationSyntax memberAccess);
Beispiel #3
0
 protected abstract bool HasNumberOfArguments(TInvocationSyntax invocation, int number);
Beispiel #4
0
 // this will return null if there's no argument in the invocation
 // the check must be done beforehand
 protected abstract SyntaxNode GetFirstArgument(TInvocationSyntax invocation);