protected static SyntaxToken CreateUniqueName( ISemanticFactsService semanticFacts, SemanticModel model, SyntaxNode location, string baseName, CancellationToken cancellationToken ) => semanticFacts.GenerateUniqueLocalName( model, location, containerOpt: null, baseName, cancellationToken );
private (SyntaxNode nodeToReplace, SyntaxNode inlineNode) GetInlineNode( TInvocationSyntax calleeInvocationNode, IMethodSymbol calleeMethodSymbol, TStatementSyntax?statementContainsInvocation, TExpressionSyntax rawInlineExpression, MethodParametersInfo methodParametersInfo, InlineMethodContext inlineMethodContext, SemanticModel semanticModel, SyntaxGenerator syntaxGenerator, CancellationToken cancellationToken) { if (statementContainsInvocation != null) { if (methodParametersInfo.MergeInlineContentAndVariableDeclarationArgument) { var rightHandSideValue = _syntaxFacts.GetRightHandSideOfAssignment(inlineMethodContext.InlineExpression); var(parameterSymbol, name) = methodParametersInfo.ParametersWithVariableDeclarationArgument.Single(); var declarationNode = (TStatementSyntax)syntaxGenerator .LocalDeclarationStatement(parameterSymbol.Type, name, rightHandSideValue); return(statementContainsInvocation, declarationNode.WithTriviaFrom(statementContainsInvocation)); } if (_syntaxFacts.IsThrowStatement(rawInlineExpression.Parent) && _syntaxFacts.IsExpressionStatement(calleeInvocationNode.Parent)) { var throwStatement = (TStatementSyntax)syntaxGenerator .ThrowStatement(inlineMethodContext.InlineExpression); return(statementContainsInvocation, throwStatement.WithTriviaFrom(statementContainsInvocation)); } if (_syntaxFacts.IsThrowExpression(rawInlineExpression) && _syntaxFacts.IsExpressionStatement(calleeInvocationNode.Parent)) { // Example: // Before: // void Caller() { Callee(); } // void Callee() => throw new Exception(); // After: // void Caller() { throw new Exception(); } // void Callee() => throw new Exception(); // Note: Throw expression is converted to throw statement var throwStatement = (TStatementSyntax)syntaxGenerator .ThrowStatement(_syntaxFacts.GetExpressionOfThrowExpression(inlineMethodContext.InlineExpression)); return(statementContainsInvocation, throwStatement.WithTriviaFrom(statementContainsInvocation)); } if (_syntaxFacts.IsExpressionStatement(calleeInvocationNode.Parent) && !calleeMethodSymbol.ReturnsVoid && !IsValidExpressionUnderExpressionStatement(inlineMethodContext.InlineExpression)) { // If the callee is invoked as ExpressionStatement, but the inlined expression in the callee can't be // placed under ExpressionStatement // Example: // void Caller() // { // Callee(); // } // int Callee() // { // return 1; // }; // After it should be: // void Caller() // { // int temp = 1; // } // int Callee() // { // return 1; // }; // One variable declaration needs to be generated. var unusedLocalName = _semanticFactsService.GenerateUniqueLocalName( semanticModel, calleeInvocationNode, containerOpt: null, TemporaryName, cancellationToken); var localDeclarationNode = (TStatementSyntax)syntaxGenerator .LocalDeclarationStatement(calleeMethodSymbol.ReturnType, unusedLocalName.Text, inlineMethodContext.InlineExpression); return(statementContainsInvocation, localDeclarationNode.WithTriviaFrom(statementContainsInvocation)); } } if (_syntaxFacts.IsThrowStatement(rawInlineExpression.Parent)) { // Example: // Before: // void Caller() => Callee(); // void Callee() { throw new Exception(); } // After: // void Caller() => throw new Exception(); // void Callee() { throw new Exception(); } // Note: Throw statement is converted to throw expression if (CanBeReplacedByThrowExpression(calleeInvocationNode)) { var throwExpression = (TExpressionSyntax)syntaxGenerator .ThrowExpression(inlineMethodContext.InlineExpression) .WithTriviaFrom(calleeInvocationNode); return(calleeInvocationNode, throwExpression.WithTriviaFrom(calleeInvocationNode)); } } var inlineExpression = inlineMethodContext.InlineExpression; if (!_syntaxFacts.IsExpressionStatement(calleeInvocationNode.Parent) && !calleeMethodSymbol.ReturnsVoid && !_syntaxFacts.IsThrowExpression(inlineMethodContext.InlineExpression)) { // Add type cast and parenthesis to the inline expression. // It is required to cover cases like: // Case 1 (parenthesis added): // Before: // void Caller() { var x = 3 * Callee(); } // int Callee() { return 1 + 2; } // // After // void Caller() { var x = 3 * (1 + 2); } // int Callee() { return 1 + 2; } // // Case 2 (type cast) // Before: // void Caller() { var x = Callee(); } // long Callee() { return 1 } // // After // void Caller() { var x = (long)1; } // int Callee() { return 1; } // // Case 3 (type cast & additional parenthesis) // Before: // void Caller() { var x = Callee()(); } // Func<int> Callee() { return () => 1; } // After: // void Caller() { var x = ((Func<int>)(() => 1))(); } // Func<int> Callee() { return () => 1; } inlineExpression = (TExpressionSyntax)syntaxGenerator.AddParentheses( syntaxGenerator.CastExpression( GenerateTypeSyntax(calleeMethodSymbol.ReturnType, allowVar: false), syntaxGenerator.AddParentheses(inlineMethodContext.InlineExpression))); } return(calleeInvocationNode, inlineExpression.WithTriviaFrom(calleeInvocationNode)); }