private static async Task <Document> RefactorAsync( Document document, SwitchStatementSyntax switchStatement, CancellationToken cancellationToken) { var nodesToRemove = new List <SyntaxNode>(); var labelsToRemove = new List <SyntaxNode>(); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); foreach (SwitchSectionSyntax section in switchStatement.Sections) { labelsToRemove.Clear(); SyntaxList <SwitchLabelSyntax> labels = section.Labels; foreach (SwitchLabelSyntax label in labels) { if (semanticModel.GetDiagnostic( CompilerDiagnosticIdentifiers.CS0152_SwitchStatementContainsMultipleCasesWithSameLabelValue, label.Span, cancellationToken) != null) { labelsToRemove.Add(label); } } if (labelsToRemove.Count == labels.Count) { nodesToRemove.Add(section); } else { nodesToRemove.AddRange(labelsToRemove); } } SwitchStatementSyntax newSwitchStatement = switchStatement .RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(switchStatement, newSwitchStatement, cancellationToken).ConfigureAwait(false)); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindToken(root, context.Span.Start, out SyntaxToken token)) { return; } SyntaxNode node = token.Parent; if (!CSharpFacts.CanHaveModifiers(node.Kind())) { node = node.FirstAncestor(f => CSharpFacts.CanHaveModifiers(f.Kind())); } Debug.Assert(node != null, $"{nameof(node)} is null"); if (node == null) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.ModifierIsNotValidForThisItem: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier)) { break; } SyntaxTokenList modifiers = SyntaxInfo.ModifierListInfo(node).Modifiers; if (modifiers.Contains(token)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, token); break; } else if (IsInterfaceMemberOrExplicitInterfaceImplementation(node)) { ModifiersCodeFixRegistrator.RemoveModifiers(context, diagnostic, node, modifiers, f => { switch (f.Kind()) { case SyntaxKind.PublicKeyword: case SyntaxKind.ProtectedKeyword: case SyntaxKind.InternalKeyword: case SyntaxKind.PrivateKeyword: case SyntaxKind.StaticKeyword: case SyntaxKind.VirtualKeyword: case SyntaxKind.OverrideKeyword: case SyntaxKind.AbstractKeyword: { return(true); } } return(false); }); } else if (node.IsKind(SyntaxKind.MethodDeclaration, SyntaxKind.PropertyDeclaration, SyntaxKind.IndexerDeclaration, SyntaxKind.EventDeclaration, SyntaxKind.EventFieldDeclaration) && node.IsParentKind(SyntaxKind.StructDeclaration) && modifiers.Contains(SyntaxKind.VirtualKeyword)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.VirtualKeyword); } else if (node.IsKind(SyntaxKind.IndexerDeclaration) && modifiers.Contains(SyntaxKind.StaticKeyword)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.StaticKeyword); } else if (node.IsKind(SyntaxKind.PropertyDeclaration, SyntaxKind.IndexerDeclaration, SyntaxKind.EventDeclaration, SyntaxKind.EventFieldDeclaration) && modifiers.Contains(SyntaxKind.AsyncKeyword)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.AsyncKeyword); } break; } case CompilerDiagnosticIdentifiers.MoreThanOneProtectionModifier: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, token); } break; } case CompilerDiagnosticIdentifiers.AccessibilityModifiersMayNotBeUsedOnAccessorsInInterface: case CompilerDiagnosticIdentifiers.AccessModifiersAreNotAllowedOnStaticConstructors: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveAccessibility(context, diagnostic, node); } break; } case CompilerDiagnosticIdentifiers.ModifiersCannotBePlacedOnEventAccessorDeclarations: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveModifiers(context, diagnostic, node); } break; } case CompilerDiagnosticIdentifiers.OnlyMethodsClassesStructsOrInterfacesMayBePartial: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.PartialKeyword); } break; } case CompilerDiagnosticIdentifiers.ClassCannotBeBothStaticAndSealed: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier)) { break; } ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.StaticKeyword, additionalKey: nameof(SyntaxKind.StaticKeyword)); ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.SealedKeyword, additionalKey: nameof(SyntaxKind.SealedKeyword)); break; } case CompilerDiagnosticIdentifiers.FieldCanNotBeBothVolatileAndReadOnly: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier)) { break; } var fieldDeclaration = (FieldDeclarationSyntax)node; ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, fieldDeclaration, SyntaxKind.VolatileKeyword, additionalKey: nameof(SyntaxKind.VolatileKeyword)); ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, fieldDeclaration, SyntaxKind.ReadOnlyKeyword, additionalKey: nameof(SyntaxKind.ReadOnlyKeyword)); break; } case CompilerDiagnosticIdentifiers.NewProtectedMemberDeclaredInSealedClass: case CompilerDiagnosticIdentifiers.StaticClassesCannotContainProtectedMembers: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeAccessibility)) { ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternalOrPrivate); } break; } case CompilerDiagnosticIdentifiers.VirtualOrAbstractMembersCannotBePrivate: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveVirtualModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.VirtualKeyword, additionalKey: nameof(SyntaxKind.VirtualKeyword)); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeAccessibility)) { ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternalOrProtected); } break; } case CompilerDiagnosticIdentifiers.AbstractPropertiesCannotHavePrivateAccessors: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveAccessibility(context, diagnostic, node, additionalKey: CodeFixIdentifiers.RemoveInvalidModifier); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeAccessibility)) { ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternalOrProtected); } break; } case CompilerDiagnosticIdentifiers.StaticMemberCannotBeMarkedOverrideVirtualOrAbstract: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier)) { break; } if (!node.IsParentKind(SyntaxKind.ClassDeclaration) || !((ClassDeclarationSyntax)node.Parent).Modifiers.Contains(SyntaxKind.StaticKeyword)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.StaticKeyword, additionalKey: nameof(SyntaxKind.StaticKeyword)); } ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.OverrideKeyword, additionalKey: nameof(SyntaxKind.OverrideKeyword)); ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.VirtualKeyword, additionalKey: nameof(SyntaxKind.VirtualKeyword)); ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.AbstractKeyword, additionalKey: nameof(SyntaxKind.AbstractKeyword)); break; } case CompilerDiagnosticIdentifiers.AsyncModifierCanOnlyBeUsedInMethodsThatHaveBody: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.AsyncKeyword); } break; } case CompilerDiagnosticIdentifiers.PartialMethodCannotHaveAccessModifiersOrVirtualAbstractOverrideNewSealedOrExternModifiers: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier)) { break; } ModifiersCodeFixRegistrator.RemoveModifiers(context, diagnostic, node, f => { switch (f.Kind()) { case SyntaxKind.PublicKeyword: case SyntaxKind.ProtectedKeyword: case SyntaxKind.InternalKeyword: case SyntaxKind.PrivateKeyword: case SyntaxKind.VirtualKeyword: case SyntaxKind.AbstractKeyword: case SyntaxKind.OverrideKeyword: case SyntaxKind.NewKeyword: case SyntaxKind.SealedKeyword: case SyntaxKind.ExternKeyword: { return(true); } } return(false); }); break; } case CompilerDiagnosticIdentifiers.ExtensionMethodMustBeStatic: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddStaticModifier)) { AddStaticModifier(context, diagnostic, node, CodeFixIdentifiers.AddStaticModifier); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveThisModifier)) { var methodDeclaration = (MethodDeclarationSyntax)node; ParameterSyntax parameter = methodDeclaration.ParameterList.Parameters[0]; SyntaxToken modifier = parameter.Modifiers.Find(SyntaxKind.ThisKeyword); ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, parameter, modifier, additionalKey: CodeFixIdentifiers.RemoveThisModifier); } break; } case CompilerDiagnosticIdentifiers.ExtensionMethodMustBeDefinedInNonGenericStaticClass: { if (!(node is ClassDeclarationSyntax classDeclaration)) { return; } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddStaticModifier) && !classDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword)) { AddStaticModifier(context, diagnostic, node, CodeFixIdentifiers.AddStaticModifier); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveThisModifier)) { IEnumerable <ParameterSyntax> thisParameters = classDeclaration.Members .Where(f => f.IsKind(SyntaxKind.MethodDeclaration)) .Cast <MethodDeclarationSyntax>() .Select(f => f.ParameterList?.Parameters.FirstOrDefault()) .Where(f => f?.Modifiers.Contains(SyntaxKind.ThisKeyword) == true); ModifiersCodeFixRegistrator.RemoveModifier( context, diagnostic, thisParameters, SyntaxKind.ThisKeyword, title: "Remove 'this' modifier from extension methods", additionalKey: CodeFixIdentifiers.RemoveThisModifier); } break; } case CompilerDiagnosticIdentifiers.NoDefiningDeclarationFoundForImplementingDeclarationOfPartialMethod: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.PartialKeyword); } break; } case CompilerDiagnosticIdentifiers.MethodHasParameterModifierThisWhichIsNotOnFirstParameter: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveThisModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, token.Parent, token); } break; } case CompilerDiagnosticIdentifiers.CannotDeclareInstanceMembersInStaticClass: case CompilerDiagnosticIdentifiers.StaticClassesCannotHaveInstanceConstructors: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddStaticModifier)) { AddStaticModifier(context, diagnostic, node, CodeFixIdentifiers.AddStaticModifier); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeContainingClassNonStatic)) { var classDeclaration = (ClassDeclarationSyntax)node.Parent; ModifiersCodeFixRegistrator.RemoveModifier( context, diagnostic, classDeclaration, classDeclaration.Modifiers.Find(SyntaxKind.StaticKeyword), title: "Make containing class non-static", additionalKey: CodeFixIdentifiers.MakeContainingClassNonStatic); } break; } case CompilerDiagnosticIdentifiers.ElementsDefinedInNamespaceCannotBeExplicitlyDeclaredAsPrivateProtectedOrProtectedInternal: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeAccessibility)) { ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternal); } break; } case CompilerDiagnosticIdentifiers.NamespaceAlreadyContainsDefinition: case CompilerDiagnosticIdentifiers.TypeAlreadyContainsDefinition: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddPartialModifier)) { break; } if (!node.IsKind( SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration, SyntaxKind.InterfaceDeclaration, SyntaxKind.MethodDeclaration)) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol symbol = semanticModel.GetDeclaredSymbol(node, context.CancellationToken); ImmutableArray <SyntaxReference> syntaxReferences = symbol.DeclaringSyntaxReferences; if (syntaxReferences.Length <= 1) { break; } ModifiersCodeFixRegistrator.AddModifier( context, diagnostic, ImmutableArray.CreateRange(syntaxReferences, f => f.GetSyntax(context.CancellationToken)), SyntaxKind.PartialKeyword, title: $"Make {CSharpFacts.GetTitle(node)} partial"); break; } case CompilerDiagnosticIdentifiers.NoSuitableMethodFoundToOverride: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.OverrideKeyword); } break; } case CompilerDiagnosticIdentifiers.AsyncMethodsCannotHaveRefOrOutParameters: case CompilerDiagnosticIdentifiers.IteratorsCannotHaveRefOrOutParameters: case CompilerDiagnosticIdentifiers.ReadOnlyFieldCannotBePassedAsRefOrOutValue: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveRefModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.RefKeyword, additionalKey: nameof(SyntaxKind.RefKeyword)); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveOutModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.OutKeyword, additionalKey: nameof(SyntaxKind.OutKeyword)); } break; } case CompilerDiagnosticIdentifiers.CannotHaveInstancePropertyOrFieldInitializersInStruct: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddStaticModifier)) { AddStaticModifier(context, diagnostic, node); } break; } case CompilerDiagnosticIdentifiers.MemberMustDeclareBodyBecauseItIsNotMarkedAbstractExternOrPartial: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddModifierAbstract) && node.Kind() == SyntaxKind.MethodDeclaration && (node.Parent as ClassDeclarationSyntax)?.Modifiers.Contains(SyntaxKind.AbstractKeyword) == true) { ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.AbstractKeyword); } break; } case CompilerDiagnosticIdentifiers.NewVirtualMemberInSealedClass: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveVirtualModifier)) { if (node is AccessorDeclarationSyntax && SyntaxInfo.ModifierListInfo(node.Parent.Parent).IsVirtual) { node = node.Parent.Parent; } ModifiersCodeFixRegistrator.RemoveModifier( context, diagnostic, node, SyntaxKind.VirtualKeyword, additionalKey: CodeFixIdentifiers.RemoveVirtualModifier); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeContainingClassUnsealed) && node.Parent is ClassDeclarationSyntax classDeclaration) { ModifiersCodeFixRegistrator.RemoveModifier( context, diagnostic, classDeclaration, SyntaxKind.SealedKeyword, title: "Make containing class unsealed", additionalKey: CodeFixIdentifiers.MakeContainingClassUnsealed); } break; } case CompilerDiagnosticIdentifiers.InstanceFieldsOfReadOnlyStructsMustBeReadOnly: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeMemberReadOnly)) { break; } ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.ReadOnlyKeyword); break; } case CompilerDiagnosticIdentifiers.MemberCannotBeSealedBecauseItIsNotOverride: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveSealedModifier)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (semanticModel.GetDiagnostic( CompilerDiagnosticIdentifiers.MemberHidesInheritedMemberToMakeCurrentMethodOverrideThatImplementationAddOverrideKeyword, CSharpUtility.GetIdentifier(node).Span, context.CancellationToken) != null) { break; } ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.SealedKeyword); break; } } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { Diagnostic diagnostic = context.Diagnostics[0]; if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MoveInitializerExpressionsToConstructor)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); ObjectCreationExpressionSyntax objectCreationExpression = root .FindNode(context.Span, getInnermostNodeForTie: true)? .FirstAncestorOrSelf <ObjectCreationExpressionSyntax>(); if (objectCreationExpression == null) { return; } switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.ThereIsNoArgumentGivenThatCorrespondsToRequiredFormalParameter: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MoveInitializerExpressionsToConstructor)) { break; } if (!objectCreationExpression.Type.Span.Contains(diagnostic.Location.SourceSpan)) { return; } ArgumentListSyntax argumentList = objectCreationExpression.ArgumentList; if (argumentList?.Arguments.Any() == true) { return; } InitializerExpressionSyntax initializer = objectCreationExpression.Initializer; if (initializer == null) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); List <ExpressionSyntax> expressions = null; foreach (ExpressionSyntax expression in initializer.Expressions) { if (expression is AssignmentExpressionSyntax assignment && semanticModel.GetDiagnostic( CompilerDiagnosticIdentifiers.PropertyOrIndexerCannotBeUsedInThisContextBecauseSetAccessorIsAccessible, assignment.Left.Span, context.CancellationToken) != null) { (expressions ??= new List <ExpressionSyntax>()).Add(expression); } } if (expressions == null) { return; } TypeSyntax type = objectCreationExpression.Type; if (argumentList == null) { argumentList = ArgumentList().WithTrailingTrivia(type.GetTrailingTrivia()); type = type.WithoutTrailingTrivia(); } SeparatedSyntaxList <ArgumentSyntax> arguments = expressions .Select(f => Argument(((AssignmentExpressionSyntax)f).Right)) .ToSeparatedSyntaxList(); argumentList = argumentList.WithArguments(arguments); ObjectCreationExpressionSyntax newObjectCreationExpression = objectCreationExpression.Update( objectCreationExpression.NewKeyword, type, argumentList, initializer); SymbolInfo symbolInfo = semanticModel.GetSpeculativeSymbolInfo( objectCreationExpression.SpanStart, newObjectCreationExpression, SpeculativeBindingOption.BindAsExpression); if (symbolInfo.Symbol is IMethodSymbol methodSymbol && methodSymbol.MethodKind == MethodKind.Constructor) { CodeAction codeAction = CodeAction.Create( "Move initializer expressions to constructor", ct => { InitializerExpressionSyntax newInitializer = initializer.RemoveNodes(expressions, SyntaxRefactorings.DefaultRemoveOptions); if (newInitializer.Expressions.Count == 0 && newInitializer .DescendantTrivia(TextSpan.FromBounds(newInitializer.OpenBraceToken.SpanStart, newInitializer.CloseBraceToken.SpanStart)) .All(f => f.IsWhitespaceOrEndOfLineTrivia())) { newInitializer = null; ArgumentListSyntax newArgumentList = newObjectCreationExpression .ArgumentList .TrimTrailingTrivia() .AppendToTrailingTrivia(initializer.GetTrailingTrivia()); newObjectCreationExpression = newObjectCreationExpression .WithArgumentList(newArgumentList); } newObjectCreationExpression = newObjectCreationExpression .WithInitializer(newInitializer) .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(objectCreationExpression, newObjectCreationExpression, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } break; } } }