public static void ChangeTypeAndAddAwait( CodeFixContext context, Diagnostic diagnostic, ExpressionSyntax expression, VariableDeclarationSyntax variableDeclaration, TypeSyntax type, ITypeSymbol newTypeSymbol, SemanticModel semanticModel) { AwaitExpressionSyntax newExpression = SyntaxFactory.AwaitExpression(expression).WithTriviaFrom(expression); VariableDeclarationSyntax newNode = variableDeclaration.ReplaceNode(expression, newExpression); TypeSyntax newType = newTypeSymbol.ToMinimalTypeSyntax(semanticModel, type.SpanStart).WithTriviaFrom(type); newNode = newNode.WithType(newType); string typeName = SymbolDisplay.GetMinimalString(newTypeSymbol, semanticModel, type.SpanStart); CodeAction codeAction = CodeAction.Create( $"Change type to '{typeName}' and add await", cancellationToken => context.Document.ReplaceNodeAsync(variableDeclaration, newNode, cancellationToken), EquivalenceKeyProvider.GetEquivalenceKey(diagnostic, CodeFixIdentifiers.ChangeTypeAccordingToInitializer + "AddAwait")); context.RegisterCodeFix(codeAction, diagnostic); }
private static void RegisterCodeFix( CodeFixContext context, Diagnostic diagnostic, SyntaxNode node, TypeSyntax type, ExpressionSyntax expression, ITypeSymbol newTypeSymbol, SemanticModel semanticModel, bool insertAwait = false, string additionalKey = null) { Document document = context.Document; string typeName = SymbolDisplay.GetMinimalString(newTypeSymbol, semanticModel, type.SpanStart); string title = $"Change {GetText(node)} type to '{typeName}'"; if (insertAwait) { title += " and insert 'await'"; } CodeAction codeAction = CodeAction.Create( title, cancellationToken => { SyntaxNode newNode = null; TypeSyntax newType = ParseTypeName(typeName) .WithTriviaFrom(type); if (insertAwait) { var nodes = new SyntaxNode[] { type, expression }; newNode = node.ReplaceNodes(nodes, (f, g) => { if (f == type) { return(newType); } else { return(AwaitExpression( Token(expression.GetLeadingTrivia(), SyntaxKind.AwaitKeyword, TriviaList(Space)), expression.WithoutLeadingTrivia())); } }); return(document.ReplaceNodeAsync(node, newNode, cancellationToken)); } else { return(document.ReplaceNodeAsync(type, newType, cancellationToken)); } }, EquivalenceKeyProvider.GetEquivalenceKey(diagnostic, CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression, additionalKey)); context.RegisterCodeFix(codeAction, diagnostic); }
public static void ComputeCodeFix( CodeFixContext context, Diagnostic diagnostic, ExpressionSyntax expression, SemanticModel semanticModel) { TypeInfo typeInfo = semanticModel.GetTypeInfo(expression, context.CancellationToken); ITypeSymbol type = typeInfo.Type; if (!(type is INamedTypeSymbol namedTypeSymbol)) { return; } ITypeSymbol convertedType = typeInfo.ConvertedType; if (type == convertedType) { return; } if (namedTypeSymbol.ConstructedFrom.SpecialType != SpecialType.System_Collections_Generic_IEnumerable_T) { return; } if (!namedTypeSymbol.TypeArguments[0].Equals(convertedType)) { return; } CodeAction codeAction = CodeAction.Create( "Replace yield return with foreach", cancellationToken => { string name = DefaultNames.ForEachVariable; name = NameGenerator.Default.EnsureUniqueLocalName(name, semanticModel, expression.SpanStart, cancellationToken: cancellationToken); ForEachStatementSyntax forEachStatement = ForEachStatement( type: VarType(), identifier: Identifier(name), expression: expression.TrimTrivia(), statement: YieldReturnStatement(IdentifierName(name))); SyntaxNode yieldStatement = expression.Parent; forEachStatement = forEachStatement.WithTriviaFrom(yieldStatement); return(context.Document.ReplaceNodeAsync(yieldStatement, forEachStatement, cancellationToken)); }, EquivalenceKeyProvider.GetEquivalenceKey(diagnostic, CodeFixIdentifiers.ReplaceYieldReturnWithForEach)); context.RegisterCodeFix(codeAction, diagnostic); }