private ITypeSymbol TryGetArgsArgumentType(
            SemanticModel semanticModel,
            SeparatedSyntaxList <SyntaxNode> arguments,
            ImmutableArray <IParameterSymbol> parameters,
            ISyntaxFactsService syntaxFacts)
        {
            var argsArgument = TryGetArgument(semanticModel, NameOfArgsParameter, arguments, parameters);

            if (argsArgument == null)
            {
                return(null);
            }

            var expression = syntaxFacts.GetExpressionOfArgument(argsArgument);

            return(semanticModel.GetTypeInfo(expression).Type);
        }
        private async Task <Document> CreateInterpolatedString(
            TInvocationExpressionSyntax invocation,
            Document document,
            ISyntaxFactsService syntaxFactsService,
            CancellationToken cancellationToken)
        {
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var arguments         = syntaxFactsService.GetArgumentsOfInvocationExpression(invocation);
            var literalExpression = syntaxFactsService.GetExpressionOfArgument(arguments[0]) as TLiteralExpressionSyntax;
            var text                  = literalExpression.GetFirstToken().ToString();
            var syntaxGenerator       = document.Project.LanguageServices.GetService <SyntaxGenerator>();
            var expandedArguments     = GetExpandedArguments(semanticModel, arguments, syntaxGenerator, syntaxFactsService);
            var interpolatedString    = GetInterpolatedString(text);
            var newInterpolatedString = VisitArguments(expandedArguments, interpolatedString, syntaxFactsService);
            var root                  = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var newRoot = root.ReplaceNode(invocation, newInterpolatedString.WithTriviaFrom(invocation));

            return(document.WithSyntaxRoot(newRoot));
        }
Example #3
0
            static bool IsValidPlaceholderToInterpolatedString(
                TInvocationExpressionSyntax invocation,
                ISyntaxFactsService syntaxFactsService,
                SemanticModel semanticModel,
                ImmutableArray <IMethodSymbol> formatMethods,
                AbstractConvertPlaceholderToInterpolatedStringRefactoringProvider <
                    TInvocationExpressionSyntax,
                    TExpressionSyntax,
                    TArgumentSyntax,
                    TLiteralExpressionSyntax,
                    TArgumentListExpressionSyntax
                    > thisInstance,
                CancellationToken cancellationToken
                )
            {
                var arguments = syntaxFactsService.GetArgumentsOfInvocationExpression(invocation);

                if (arguments.Count >= 2)
                {
                    if (
                        syntaxFactsService.GetExpressionOfArgument(
                            GetFormatArgument(arguments, syntaxFactsService)
                            )
                        is TLiteralExpressionSyntax firstArgumentExpression &&
                        syntaxFactsService.IsStringLiteral(
                            firstArgumentExpression.GetFirstToken()
                            )
                        )
                    {
                        var invocationSymbol =
                            semanticModel.GetSymbolInfo(invocation, cancellationToken).Symbol;
                        if (formatMethods.Contains(invocationSymbol))
                        {
                            return(true);
                        }
                    }
                }

                return(false);
            }
Example #4
0
        protected SyntaxNode?TryGetFormatStringLiteralExpressionSyntax(
            SeparatedSyntaxList <SyntaxNode> arguments,
            ImmutableArray <IParameterSymbol> parameters,
            ISyntaxFactsService syntaxFacts)
        {
            var formatArgumentSyntax = TryGetArgument(
                NameOfFormatStringParameter,
                arguments,
                parameters);

            if (formatArgumentSyntax == null)
            {
                return(null);
            }

            if (!syntaxFacts.IsStringLiteralExpression(syntaxFacts.GetExpressionOfArgument(formatArgumentSyntax)))
            {
                return(null);
            }

            return(GetArgumentExpression(formatArgumentSyntax));
        }
Example #5
0
        private static TArgumentSyntax DetermineFirstArgumentToAdd(
            SemanticModel semanticModel,
            ISyntaxFactsService syntaxFacts,
            StringComparer comparer,
            IMethodSymbol method,
            SeparatedSyntaxList <TArgumentSyntax> arguments)
        {
            var compilation          = semanticModel.Compilation;
            var methodParameterNames = new HashSet <string>(comparer);

            methodParameterNames.AddRange(method.Parameters.Select(p => p.Name));

            for (int i = 0, n = arguments.Count; i < n; i++)
            {
                var argument     = arguments[i];
                var argumentName = syntaxFacts.GetNameForArgument(argument);

                if (!string.IsNullOrWhiteSpace(argumentName))
                {
                    // If the user provided an argument-name and we don't have any parameters that
                    // match, then this is the argument we want to add a parameter for.
                    if (!methodParameterNames.Contains(argumentName))
                    {
                        return(argument);
                    }
                }
                else
                {
                    // Positional argument.  If the position is beyond what the method supports,
                    // then this definitely is an argument we could add.
                    if (i >= method.Parameters.Length)
                    {
                        if (method.Parameters.LastOrDefault()?.IsParams == true)
                        {
                            // Last parameter is a params.  We can't place any parameters past it.
                            return(null);
                        }

                        return(argument);
                    }

                    // Now check the type of the argument versus the type of the parameter.  If they
                    // don't match, then this is the argument we should make the parameter for.
                    var expressionOfArgument = syntaxFacts.GetExpressionOfArgument(argument);
                    if (expressionOfArgument is null)
                    {
                        return(null);
                    }
                    var argumentTypeInfo = semanticModel.GetTypeInfo(expressionOfArgument);
                    var isNullLiteral    = syntaxFacts.IsNullLiteralExpression(expressionOfArgument);
                    var isDefaultLiteral = syntaxFacts.IsDefaultLiteralExpression(expressionOfArgument);

                    if (argumentTypeInfo.Type == null && argumentTypeInfo.ConvertedType == null)
                    {
                        // Didn't know the type of the argument.  We shouldn't assume it doesn't
                        // match a parameter.  However, if the user wrote 'null' and it didn't
                        // match anything, then this is the problem argument.
                        if (!isNullLiteral && !isDefaultLiteral)
                        {
                            continue;
                        }
                    }

                    var parameter = method.Parameters[i];

                    if (!TypeInfoMatchesType(
                            compilation, argumentTypeInfo, parameter.Type,
                            isNullLiteral, isDefaultLiteral))
                    {
                        if (TypeInfoMatchesWithParamsExpansion(
                                compilation, argumentTypeInfo, parameter,
                                isNullLiteral, isDefaultLiteral))
                        {
                            // The argument matched if we expanded out the params-parameter.
                            // As the params-parameter has to be last, there's nothing else to
                            // do here.
                            return(null);
                        }

                        return(argument);
                    }
                }
            }

            return(null);
        }
Example #6
0
 private bool MatchesPattern(ISyntaxFactsService syntaxFacts, SyntaxNode node1, SyntaxNode node2)
 => syntaxFacts.IsNullLiteralExpression(syntaxFacts.GetExpressionOfArgument(node1)) &&
 !syntaxFacts.IsNullLiteralExpression(syntaxFacts.GetExpressionOfArgument(node2));