public static async Task <Document> RefactorAsync( Document document, ForStatementSyntax forStatement, CancellationToken cancellationToken = default(CancellationToken)) { SyntaxNode oldRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); IEnumerable <IdentifierNameSyntax> identifierNames = await GetIdentifierNamesAsync(document, forStatement, oldRoot, semanticModel, cancellationToken).ConfigureAwait(false); List <ElementAccessExpressionSyntax> expressions = identifierNames .Select(f => f.Parent.Parent.Parent) .Cast <ElementAccessExpressionSyntax>() .ToList(); var rewriter = new ForToForEachSyntaxRewriter(expressions, ElementName); ForEachStatementSyntax forEachStatement = ForEachStatement( IdentifierName("var"), ElementName, GetCollectionExpression(forStatement), (StatementSyntax)rewriter.Visit(forStatement.Statement)); forEachStatement = forEachStatement .WithTriviaFrom(forStatement) .WithFormatterAnnotation(); SyntaxNode newRoot = oldRoot.ReplaceNode(forStatement, forEachStatement); return(document.WithSyntaxRoot(newRoot)); }
public static async Task <Document> RefactorAsync( Document document, ForStatementSyntax forStatement, CancellationToken cancellationToken = default(CancellationToken)) { StatementSyntax statement = forStatement.Statement; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); string identifier = Identifier.EnsureUniqueLocalName(Identifier.DefaultForEachVariableName, statement.SpanStart, semanticModel, cancellationToken); IdentifierNameSyntax identifierName = IdentifierName(identifier); var condition = (BinaryExpressionSyntax)forStatement.Condition; var memberAccessExpression = (MemberAccessExpressionSyntax)condition.Right; ExpressionSyntax expression = memberAccessExpression.Expression; ISymbol symbol = semanticModel.GetDeclaredSymbol(forStatement.Declaration.Variables.First(), cancellationToken); ImmutableArray <SyntaxNode> nodes = await document.FindSymbolNodesAsync(symbol, cancellationToken).ConfigureAwait(false); StatementSyntax newStatement = statement.ReplaceNodes( nodes.Select(f => f.Parent.Parent.Parent), (f, g) => identifierName.WithTriviaFrom(f)); ForEachStatementSyntax forEachStatement = ForEachStatement( VarType(), identifier, expression, newStatement); forEachStatement = forEachStatement .WithTriviaFrom(forStatement) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(forStatement, forEachStatement, cancellationToken).ConfigureAwait(false)); }
public static async Task <Document> RefactorAsync( Document document, ForStatementSyntax forStatement, CancellationToken cancellationToken = default) { StatementSyntax statement = forStatement.Statement; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); string name = NameGenerator.Default.EnsureUniqueLocalName( DefaultNames.ForEachVariable, semanticModel, statement.SpanStart, cancellationToken: cancellationToken); IdentifierNameSyntax identifierName = IdentifierName(name); var condition = (BinaryExpressionSyntax)forStatement.Condition; var memberAccessExpression = (MemberAccessExpressionSyntax)condition.Right; ExpressionSyntax expression = memberAccessExpression.Expression; ISymbol symbol = semanticModel.GetDeclaredSymbol(forStatement.Declaration.Variables[0], cancellationToken); ImmutableArray <SyntaxNode> nodes = await SyntaxFinder.FindReferencesAsync(symbol, document, cancellationToken : cancellationToken).ConfigureAwait(false); StatementSyntax newStatement = statement.ReplaceNodes( nodes.Select(f => f.Parent.Parent.Parent), (f, _) => identifierName.WithTriviaFrom(f)); TypeSyntax type = VarType(); if (semanticModel.GetTypeSymbol(expression, cancellationToken) is INamedTypeSymbol namedType && !namedType.OriginalDefinition.Implements(SpecialType.System_Collections_Generic_IEnumerable_T, allInterfaces: true)) { IPropertySymbol member = namedType.FindMember <IPropertySymbol>( "this[]", f => f.Parameters.SingleOrDefault(shouldThrow: false)?.Type.SpecialType == SpecialType.System_Int32, includeBaseTypes: true); Debug.Assert(member != null, ""); if (member != null) { type = member.Type.ToTypeSyntax().WithSimplifierAnnotation(); } } ForEachStatementSyntax forEachStatement = ForEachStatement( type, Identifier(name).WithRenameAnnotation(), expression, newStatement); forEachStatement = forEachStatement .WithTriviaFrom(forStatement) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(forStatement, forEachStatement, cancellationToken).ConfigureAwait(false)); }
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); }
private static Task <Document> RefactorAsync( Document document, ExpressionSyntax expression, SemanticModel semanticModel, System.Threading.CancellationToken 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(document.ReplaceNodeAsync(yieldStatement, forEachStatement, cancellationToken)); }
private static async Task <Document> RefactorAsync( Document document, UsingStatementSyntax usingStatement, CancellationToken cancellationToken) { VariableDeclaratorSyntax declarator = usingStatement.Declaration.Variables.Single(); var whileStatement = (WhileStatementSyntax)usingStatement.Statement.SingleNonBlockStatementOrDefault(); SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(declarator.Initializer.Value); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); string name = NameGenerator.Default.EnsureUniqueLocalName(DefaultNames.ForEachVariable, semanticModel, usingStatement.SpanStart, cancellationToken: cancellationToken); StatementSyntax statement = whileStatement.Statement; var rewriter = new Rewriter( semanticModel.GetDeclaredSymbol(declarator, cancellationToken), declarator.Identifier.ValueText, name, semanticModel, cancellationToken); var newStatement = (StatementSyntax)rewriter.Visit(statement); ForEachStatementSyntax forEachStatement = ForEachStatement( VarType(), Identifier(name).WithRenameAnnotation(), invocationInfo.Expression, newStatement); forEachStatement = forEachStatement .WithTriviaFrom(usingStatement) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(usingStatement, forEachStatement, cancellationToken).ConfigureAwait(false)); }