public static async Task <Solution> RefactorAsync( Document document, FieldDeclarationSyntax fieldDeclaration, VariableDeclaratorSyntax variableDeclarator, CancellationToken cancellationToken) { ExpressionSyntax value = variableDeclarator.Initializer.Value; ParenthesizedExpressionSyntax newValue = value .Parenthesize(moveTrivia: true) .WithSimplifierAnnotation(); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ISymbol symbol = semanticModel.GetDeclaredSymbol(variableDeclarator, cancellationToken); IEnumerable <ReferencedSymbol> referencedSymbols = await SymbolFinder.FindReferencesAsync(symbol, document.Solution(), cancellationToken).ConfigureAwait(false); var newDocuments = new List <KeyValuePair <DocumentId, SyntaxNode> >(); foreach (IGrouping <Document, ReferenceLocation> grouping in referencedSymbols .First() .Locations .Where(f => !f.IsImplicit && !f.IsCandidateLocation) .GroupBy(f => f.Document)) { SyntaxNode root = await grouping.Key.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxNode newRoot = root.ReplaceNodes( GetNodesToReplace(grouping.AsEnumerable(), root, fieldDeclaration, variableDeclarator), (f, g) => { if (f.IsKind(SyntaxKind.FieldDeclaration, SyntaxKind.VariableDeclarator)) { return(f.WithAdditionalAnnotations(_removeAnnotation)); } return(newValue); }); SyntaxNode nodeToRemove = newRoot.GetAnnotatedNodes(_removeAnnotation).FirstOrDefault(); if (nodeToRemove != null) { newRoot = newRoot.RemoveNode(nodeToRemove, RemoveHelper.GetRemoveOptions(nodeToRemove)); } newDocuments.Add(new KeyValuePair <DocumentId, SyntaxNode>(grouping.Key.Id, newRoot)); } Solution newSolution = document.Solution(); foreach (KeyValuePair <DocumentId, SyntaxNode> kvp in newDocuments) { newSolution = newSolution.WithDocumentSyntaxRoot(kvp.Key, kvp.Value); } return(newSolution); }
private static void RemoveConstraint( CodeFixContext context, Diagnostic diagnostic, TypeParameterConstraintSyntax constraint) { CodeAction codeAction = CodeAction.Create( $"Remove constraint '{constraint}'", cancellationToken => context.Document.RemoveNodeAsync(constraint, RemoveHelper.GetRemoveOptions(constraint), cancellationToken), GetEquivalenceKey(diagnostic, constraint.Kind().ToString())); context.RegisterCodeFix(codeAction, diagnostic); }
public static Task <Document> RefactorAsync( Document document, ThrowStatementSyntax throwStatement, CancellationToken cancellationToken = default(CancellationToken)) { ExpressionSyntax expression = throwStatement.Expression; ThrowStatementSyntax newThrowStatement = throwStatement .RemoveNode(expression, RemoveHelper.GetRemoveOptions(expression)) .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(throwStatement, newThrowStatement, cancellationToken)); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveAttribute)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out AttributeSyntax attribute)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.AttributeIsNotValidOnThisDeclarationType: case CompilerDiagnosticIdentifiers.AttributeIsOnlyValidOnMethodsOrAttributeClasses: { CodeAction codeAction = CodeAction.Create( $"Remove attribute '{attribute.Name}'", cancellationToken => { var attributeList = (AttributeListSyntax)attribute.Parent; SeparatedSyntaxList <AttributeSyntax> attributes = attributeList.Attributes; if (attributes.Count == 1) { return(context.Document.RemoveNodeAsync(attributeList, RemoveHelper.GetRemoveOptions(attributeList), cancellationToken)); } else { return(context.Document.RemoveNodeAsync(attribute, RemoveHelper.GetRemoveOptions(attributeList), cancellationToken)); } }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }
public static Task <Document> RefactorAsync( Document document, SyntaxNode node, CancellationToken cancellationToken) { if (node.Kind() == SyntaxKind.VariableDeclarator) { var variableDeclaration = (VariableDeclarationSyntax)node.Parent; if (variableDeclaration.Variables.Count == 1) { SyntaxNode parent = variableDeclaration.Parent; return(document.RemoveNodeAsync(parent, RemoveHelper.GetRemoveOptions(parent), cancellationToken)); } } return(document.RemoveNodeAsync(node, RemoveHelper.GetRemoveOptions(node), cancellationToken)); }
public static Task <Document> RefactorAsync( Document document, InvocationExpressionSyntax invocation, CancellationToken cancellationToken) { var memberAccess = (MemberAccessExpressionSyntax)invocation.Expression; ArgumentSyntax lastArgument = invocation.ArgumentList.Arguments.Last(); var lambdaExpression = (LambdaExpressionSyntax)lastArgument.Expression; GenericNameSyntax newName = GenericName( Identifier("Cast"), GetCastExpression(lambdaExpression.Body).Type); InvocationExpressionSyntax newInvocation = invocation .RemoveNode(lastArgument, RemoveHelper.GetRemoveOptions(lastArgument)) .WithExpression(memberAccess.WithName(newName)); return(document.ReplaceNodeAsync(invocation, newInvocation, cancellationToken)); }
private static SyntaxNode RemoveUsingDirective(SyntaxNode node, int index) { switch (node.Kind()) { case SyntaxKind.CompilationUnit: { var compilationUnit = (CompilationUnitSyntax)node; UsingDirectiveSyntax usingDirective = compilationUnit.Usings[index]; return(compilationUnit.RemoveNode(usingDirective, RemoveHelper.GetRemoveOptions(usingDirective))); } case SyntaxKind.NamespaceDeclaration: { var namespaceDeclaration = (NamespaceDeclarationSyntax)node; UsingDirectiveSyntax usingDirective = namespaceDeclaration.Usings[index]; return(namespaceDeclaration.RemoveNode(usingDirective, RemoveHelper.GetRemoveOptions(usingDirective))); } } return(node); }
private void RemoveConstraint( CodeFixContext context, Diagnostic diagnostic, TypeParameterConstraintSyntax constraint) { SeparatedSyntaxList <TypeParameterConstraintSyntax> constraints; if (GenericDeclarationHelper.TryGetContainingList(constraint, out constraints)) { CodeAction codeAction = CodeAction.Create( $"Remove constraint '{constraint}'", cancellationToken => context.Document.RemoveNodeAsync(constraint, RemoveHelper.GetRemoveOptions(constraint), cancellationToken), GetEquivalenceKey(diagnostic, constraint.Kind().ToString())); context.RegisterCodeFix(codeAction, diagnostic); } }
private static async Task <StatementsInfo> RefactorAsync( Document document, StatementsInfo statementsInfo, StatementSyntax statement, StatementSyntax newStatement, int index, int count, bool removeReturnStatement, SemanticModel semanticModel, CancellationToken cancellationToken) { ReturnStatementSyntax returnStatement = FindReturnStatementBelow(statementsInfo.Statements, index); ExpressionSyntax expression = returnStatement.Expression; ExpressionSyntax newExpression = null; ISymbol symbol = semanticModel.GetSymbol(expression, cancellationToken); if (symbol.IsLocal() && index > 0) { LocalDeclarationStatementSyntax localDeclarationStatement = FindLocalDeclarationStatementAbove(statementsInfo.Statements, index); if (localDeclarationStatement?.ContainsDiagnostics == false && !localDeclarationStatement.SpanOrTrailingTriviaContainsDirectives() && !statement.GetLeadingTrivia().Any(f => f.IsDirective)) { SeparatedSyntaxList <VariableDeclaratorSyntax> declarators = localDeclarationStatement.Declaration.Variables; VariableDeclaratorSyntax declarator = FindVariableDeclarator(semanticModel, symbol, declarators, cancellationToken); if (declarator != null) { ExpressionSyntax value = declarator.Initializer?.Value; if (removeReturnStatement || value != null) { IEnumerable <ReferencedSymbol> referencedSymbols = await SymbolFinder.FindReferencesAsync(symbol, document.Solution(), cancellationToken).ConfigureAwait(false); if (referencedSymbols.First().Locations.Count() == count + 1) { newExpression = value; if (declarators.Count == 1) { statementsInfo = statementsInfo.RemoveNode(localDeclarationStatement, RemoveHelper.GetRemoveOptions(localDeclarationStatement)); index--; } else { statementsInfo = statementsInfo.ReplaceNode(localDeclarationStatement, localDeclarationStatement.RemoveNode(declarator, RemoveHelper.GetRemoveOptions(declarator))); } returnStatement = FindReturnStatementBelow(statementsInfo.Statements, index); } } } } } if (removeReturnStatement) { statementsInfo = statementsInfo.RemoveNode(returnStatement, RemoveHelper.GetRemoveOptions(returnStatement)); } else if (newExpression != null) { statementsInfo = statementsInfo.ReplaceNode(returnStatement, returnStatement.WithExpression(newExpression.WithTriviaFrom(expression))); } return(statementsInfo.ReplaceNode(statementsInfo.Statements[index], newStatement)); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsAnyCodeFixEnabled( CodeFixIdentifiers.ChangeTypeOfParamsParameter, CodeFixIdentifiers.RemoveDefaultValueFromParameter)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out ParameterSyntax parameter)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.ParamsParameterMustBeSingleDimensionalArray: { TypeSyntax type = parameter.Type; if (type?.IsMissing == false) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, context.CancellationToken); if (typeSymbol?.IsNamedType() == true) { ArrayTypeSyntax newType = SyntaxFactory.ArrayType( typeSymbol.ToMinimalTypeSyntax(semanticModel, parameter.SpanStart), SyntaxFactory.SingletonList(SyntaxFactory.ArrayRankSpecifier())); CodeAction codeAction = CodeAction.Create( $"Change parameter type to '{newType}'", cancellationToken => context.Document.ReplaceNodeAsync(type, newType.WithTriviaFrom(type), cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } } break; } case CompilerDiagnosticIdentifiers.CannotSpecifyDefaultValueForParameterArray: { EqualsValueClauseSyntax defaultValue = parameter.Default; CodeAction codeAction = CodeAction.Create( "Remove default value from parameter", cancellationToken => { ParameterSyntax newParameter = parameter .RemoveNode(defaultValue, RemoveHelper.GetRemoveOptions(defaultValue)) .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(parameter, newParameter, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }
private static CodeAction CreateCodeActionForIfElse(Document document, Diagnostic diagnostic, SyntaxNode node) { switch (node?.Kind()) { case SyntaxKind.IfStatement: { var ifStatement = (IfStatementSyntax)node; StatementSyntax statement = ifStatement.Else?.Statement; if (statement != null) { if (statement.IsKind(SyntaxKind.Block)) { var block = (BlockSyntax)statement; SyntaxList <StatementSyntax> statements = block.Statements; if (statements.Any()) { return(CreateCodeAction(document, diagnostic, ifStatement, statements)); } } else { return(CreateCodeAction(document, diagnostic, ifStatement, statement)); } } return(CodeAction.Create( Title, cancellationToken => document.RemoveStatementAsync(ifStatement, cancellationToken), GetEquivalenceKey(diagnostic))); } case SyntaxKind.ElseClause: { var elseClause = (ElseClauseSyntax)node; if (elseClause.IsParentKind(SyntaxKind.IfStatement)) { var ifStatement = (IfStatementSyntax)elseClause.Parent; if (ifStatement.IsTopmostIf()) { StatementSyntax statement = ifStatement.Statement; if (statement != null) { if (statement.IsKind(SyntaxKind.Block)) { var block = (BlockSyntax)statement; SyntaxList <StatementSyntax> statements = block.Statements; if (statements.Any()) { return(CreateCodeAction(document, diagnostic, ifStatement, statements)); } } else { return(CreateCodeAction(document, diagnostic, ifStatement, statement)); } } } } return(CodeAction.Create( Title, cancellationToken => document.RemoveNodeAsync(elseClause, RemoveHelper.GetRemoveOptions(elseClause), cancellationToken), GetEquivalenceKey(diagnostic))); } case SyntaxKind.Block: { return(CreateCodeActionForIfElse(document, diagnostic, node.Parent)); } } return(null); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemovePropertyOrFieldInitializer)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); SyntaxToken token = root.FindToken(context.Span.Start); Debug.Assert(token.IsKind(SyntaxKind.IdentifierToken), $"{nameof(token)} is not IdentifierToken"); if (!token.IsKind(SyntaxKind.IdentifierToken)) { return; } SyntaxNode parent = token.Parent; switch (parent.Kind()) { case SyntaxKind.PropertyDeclaration: { var propertyDeclaration = (PropertyDeclarationSyntax)parent; EqualsValueClauseSyntax initializer = propertyDeclaration.Initializer; CodeAction codeAction = CodeAction.Create( Title, cancellationToken => { PropertyDeclarationSyntax newNode = propertyDeclaration .RemoveNode(initializer, RemoveHelper.GetRemoveOptions(initializer)) .WithSemicolonToken(default(SyntaxToken)) .AppendToTrailingTrivia(propertyDeclaration.SemicolonToken.GetLeadingAndTrailingTrivia()) .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(propertyDeclaration, newNode, cancellationToken)); }, GetEquivalenceKey(CompilerDiagnosticIdentifiers.CannotHaveInstancePropertyOrFieldInitializersInStruct)); context.RegisterCodeFix(codeAction, context.Diagnostics); break; } case SyntaxKind.VariableDeclarator: { var variableDeclarator = (VariableDeclaratorSyntax)parent; EqualsValueClauseSyntax initializer = variableDeclarator.Initializer; CodeAction codeAction = CodeAction.Create( Title, cancellationToken => { VariableDeclaratorSyntax newNode = variableDeclarator .RemoveNode(initializer, RemoveHelper.GetRemoveOptions(initializer)) .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(variableDeclarator, newNode, cancellationToken)); }, GetEquivalenceKey(CompilerDiagnosticIdentifiers.CannotHaveInstancePropertyOrFieldInitializersInStruct)); context.RegisterCodeFix(codeAction, context.Diagnostics); break; } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveUnusedVariable)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindToken(root, context.Span.Start, out SyntaxToken token)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.VariableIsDeclaredButNeverUsed: case CompilerDiagnosticIdentifiers.VariableIsAssignedButItsValueIsNeverUsed: { switch (token.Parent.Kind()) { case SyntaxKind.VariableDeclarator: { var variableDeclarator = (VariableDeclaratorSyntax)token.Parent; var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent; if (variableDeclaration.Variables.Count == 1) { var localDeclarationStatement = (LocalDeclarationStatementSyntax)variableDeclaration.Parent; if (!localDeclarationStatement.IsEmbedded() && !localDeclarationStatement.SpanContainsDirectives()) { CodeAction codeAction = CodeAction.Create( "Remove unused variable", cancellationToken => context.Document.RemoveNodeAsync(localDeclarationStatement, RemoveHelper.GetRemoveOptions(localDeclarationStatement), cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } } else if (!variableDeclarator.SpanContainsDirectives()) { CodeAction codeAction = CodeAction.Create( "Remove unused variable", cancellationToken => context.Document.RemoveNodeAsync(variableDeclarator, RemoveHelper.GetRemoveOptions(variableDeclarator), cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } break; } case SyntaxKind.CatchDeclaration: { var catchDeclaration = (CatchDeclarationSyntax)token.Parent; CodeAction codeAction = CodeAction.Create( "Remove unused variable", cancellationToken => { CatchDeclarationSyntax newNode = catchDeclaration .WithIdentifier(default(SyntaxToken)) .WithCloseParenToken(catchDeclaration.CloseParenToken.PrependToLeadingTrivia(token.GetLeadingAndTrailingTrivia())) .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(catchDeclaration, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case SyntaxKind.LocalFunctionStatement: { var localFunction = (LocalFunctionStatementSyntax)token.Parent; CodeAction codeAction = CodeAction.Create( "Remove unused local function", cancellationToken => context.Document.RemoveStatementAsync(localFunction, cancellationToken), GetEquivalenceKey(diagnostic, "LocalFunction")); context.RegisterCodeFix(codeAction, diagnostic); break; } } break; } } } }