public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { 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 DiagnosticIdentifiers.OverridingMemberCannotChangeParamsModifier: { if (parameter.IsParams()) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, parameter, SyntaxKind.ParamsKeyword); } else { ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, parameter, SyntaxKind.ParamsKeyword); } break; } } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsAnyEnabled( CodeFixIdentifiers.AddOverrideModifier, CodeFixIdentifiers.AddNewModifier, CodeFixIdentifiers.RemoveMemberDeclaration)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.MemberHidesInheritedMemberUseNewKeywordIfHidingWasIntended: { if (Settings.IsEnabled(CodeFixIdentifiers.AddNewModifier)) { ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, memberDeclaration, SyntaxKind.NewKeyword, additionalKey: nameof(SyntaxKind.NewKeyword)); } if (Settings.IsEnabled(CodeFixIdentifiers.RemoveMemberDeclaration)) { CodeFixRegistrator.RemoveMemberDeclaration(context, diagnostic, memberDeclaration); } break; } case CompilerDiagnosticIdentifiers.MemberHidesInheritedMemberToMakeCurrentMethodOverrideThatImplementationAddOverrideKeyword: { if (Settings.IsEnabled(CodeFixIdentifiers.AddOverrideModifier) && !SyntaxInfo.ModifierListInfo(memberDeclaration).IsStatic) { ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, memberDeclaration, SyntaxKind.OverrideKeyword, additionalKey: nameof(SyntaxKind.OverrideKeyword)); } if (Settings.IsEnabled(CodeFixIdentifiers.AddNewModifier)) { ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, memberDeclaration, SyntaxKind.NewKeyword, additionalKey: nameof(SyntaxKind.NewKeyword)); } if (Settings.IsEnabled(CodeFixIdentifiers.RemoveMemberDeclaration)) { CodeFixRegistrator.RemoveMemberDeclaration(context, diagnostic, memberDeclaration); } break; } } } }
private static void AddStaticModifier(CodeFixContext context, Diagnostic diagnostic, SyntaxNode node, string additionalKey = null) { if (node.IsKind(SyntaxKind.ConstructorDeclaration) && ((ConstructorDeclarationSyntax)node).ParameterList?.Parameters.Any() == true) { return; } ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.StaticKeyword, additionalKey: additionalKey); }
private void AddStaticModifier( CodeFixContext context, Diagnostic diagnostic, SyntaxNode node, SemanticModel semanticModel) { ISymbol symbol = semanticModel.GetSymbol(node, context.CancellationToken); if (symbol == null) { return; } SyntaxNode syntax = symbol.GetSyntaxOrDefault(context.CancellationToken); if (syntax == null) { return; } if (syntax.Kind() == SyntaxKind.VariableDeclarator) { syntax = syntax.Parent?.Parent; } Debug.Assert(syntax.IsKind(SyntaxKind.EventDeclaration, SyntaxKind.EventFieldDeclaration, SyntaxKind.FieldDeclaration, SyntaxKind.MethodDeclaration, SyntaxKind.PropertyDeclaration), syntax.ToString()); if (!(syntax is MemberDeclarationSyntax memberDeclaration)) { return; } if (memberDeclaration.GetModifiers().Contains(SyntaxKind.StaticKeyword)) { return; } Document document = context.Document; SyntaxTree tree = memberDeclaration.SyntaxTree; if (tree != node.SyntaxTree) { document = context.Solution().GetDocument(tree); } ModifiersCodeFixRegistrator.AddModifier( context, document, diagnostic, memberDeclaration, SyntaxKind.StaticKeyword, title: $"Make '{symbol.Name}' static", additionalKey: CodeFixIdentifiers.AddStaticModifier); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out ParameterSyntax parameter)) { return; } ModifiersCodeFixRegistrator.AddModifier( context, context.Diagnostics[0], parameter, SyntaxKind.InKeyword); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { 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 DiagnosticIdentifiers.OverridingMemberShouldNotChangeParamsModifier: { if (parameter.IsParams()) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, parameter, SyntaxKind.ParamsKeyword); } else { ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, parameter, SyntaxKind.ParamsKeyword); } break; } case DiagnosticIdentifiers.MakeParameterRefReadOnly: case DiagnosticIdentifiers.DoNotPassNonReadOnlyStructByReadOnlyReference: { if (parameter.Modifiers.Contains(SyntaxKind.InKeyword)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, parameter, SyntaxKind.InKeyword); } else { ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, parameter, SyntaxKind.InKeyword); } break; } } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { 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 DiagnosticIdentifiers.AddParameterToDocumentationComment: { var refactoring = new AddParameterToDocumentationCommentRefactoring(); CodeAction codeAction = CodeAction.Create( "Add parameter to documentation comment", cancellationToken => refactoring.RefactorAsync(context.Document, parameter, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.OverridingMemberCannotChangeParamsModifier: { if (parameter.IsParams()) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, parameter, SyntaxKind.ParamsKeyword); } else { ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, parameter, SyntaxKind.ParamsKeyword); } break; } } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddDocumentationComment) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveParametersFromStaticConstructor) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveMemberDeclaration) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RenameDestructorToMatchClassName) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RenameTupleElement)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.MissingXmlCommentForPubliclyVisibleTypeOrMember: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddDocumentationComment)) { break; } CodeAction codeAction = CodeAction.Create( "Add documentation comment", cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, false, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); CodeAction codeAction2 = CodeAction.Create( "Add documentation comment (copy from base if available)", cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, true, cancellationToken), GetEquivalenceKey(diagnostic, "CopyFromBaseIfAvailable")); context.RegisterCodeFix(codeAction2, diagnostic); break; } case CompilerDiagnosticIdentifiers.MethodReturnTypeMustMatchOverriddenMethodReturnType: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); ITypeSymbol typeSymbol = methodSymbol.OverriddenMethod.ReturnType; CodeFixRegistrator.ChangeMemberDeclarationType(context, diagnostic, memberDeclaration, typeSymbol, semanticModel); break; } case CompilerDiagnosticIdentifiers.PartialMethodsMustHaveVoidReturnType: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var methodDeclaration = (MethodDeclarationSyntax)memberDeclaration; MethodDeclarationSyntax otherPart = semanticModel.GetOtherPart(methodDeclaration, context.CancellationToken); if (otherPart == null) { break; } CodeAction codeAction = CodeAction.Create( "Change return type to 'void'", cancellationToken => { return(context.Document.Solution().ReplaceNodesAsync( new MethodDeclarationSyntax[] { methodDeclaration, otherPart }, (node, _) => node.WithReturnType(CSharpFactory.VoidType().WithTriviaFrom(node.ReturnType)), cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.MemberTypeMustMatchOverriddenMemberType: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ITypeSymbol typeSymbol = null; switch (memberDeclaration.Kind()) { case SyntaxKind.PropertyDeclaration: case SyntaxKind.IndexerDeclaration: { var propertySymbol = (IPropertySymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); typeSymbol = propertySymbol.OverriddenProperty.Type; break; } case SyntaxKind.EventDeclaration: { var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); typeSymbol = eventSymbol.OverriddenEvent.Type; break; } case SyntaxKind.EventFieldDeclaration: { VariableDeclaratorSyntax declarator = ((EventFieldDeclarationSyntax)memberDeclaration).Declaration.Variables.First(); var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(declarator, context.CancellationToken); typeSymbol = eventSymbol.OverriddenEvent.Type; break; } } CodeFixRegistrator.ChangeMemberDeclarationType(context, diagnostic, memberDeclaration, typeSymbol, semanticModel); break; } case CompilerDiagnosticIdentifiers.MissingPartialModifier: case CompilerDiagnosticIdentifiers.PartialMethodMustBeDeclaredInPartialClassOrPartialStruct: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier)) { break; } SyntaxNode node = null; switch (memberDeclaration.Kind()) { case SyntaxKind.MethodDeclaration: { if (memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration)) { node = memberDeclaration.Parent; } break; } case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: { node = memberDeclaration; break; } } Debug.Assert(node != null, memberDeclaration.ToString()); if (node == null) { break; } ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.PartialKeyword); break; } case CompilerDiagnosticIdentifiers.MemberIsAbstractButItIsContainedInNonAbstractClass: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract)) { break; } if (!memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration)) { break; } ModifiersCodeFixRegistrator.AddModifier( context, diagnostic, memberDeclaration.Parent, SyntaxKind.AbstractKeyword, title: "Make containing class abstract"); break; } case CompilerDiagnosticIdentifiers.StaticConstructorMustBeParameterless: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveParametersFromStaticConstructor)) { break; } var constructorDeclaration = (ConstructorDeclarationSyntax)memberDeclaration; CodeAction codeAction = CodeAction.Create( "Remove parameters", cancellationToken => { ParameterListSyntax parameterList = constructorDeclaration.ParameterList; ParameterListSyntax newParameterList = parameterList .WithParameters(default(SeparatedSyntaxList <ParameterSyntax>)) .WithOpenParenToken(parameterList.OpenParenToken.WithoutTrailingTrivia()) .WithCloseParenToken(parameterList.CloseParenToken.WithoutLeadingTrivia()); ConstructorDeclarationSyntax newNode = constructorDeclaration.WithParameterList(newParameterList); return(context.Document.ReplaceNodeAsync(constructorDeclaration, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.ExplicitInterfaceDeclarationCanOnlyBeDeclaredInClassOrStruct: case CompilerDiagnosticIdentifiers.InterfacesCannotContainFields: case CompilerDiagnosticIdentifiers.InterfacesCannotContainOperators: case CompilerDiagnosticIdentifiers.InterfacesCannotDeclareTypes: case CompilerDiagnosticIdentifiers.OnlyClassTypesCanContainDestructors: case CompilerDiagnosticIdentifiers.StructsCannotContainExplicitParameterlessConstructors: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveMemberDeclaration)) { break; } CodeFixRegistrator.RemoveMember(context, diagnostic, memberDeclaration); break; } case CompilerDiagnosticIdentifiers.NameOfDestructorMustMatchNameOfClass: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RenameDestructorToMatchClassName)) { break; } if (!(memberDeclaration is DestructorDeclarationSyntax destructorDeclaration)) { break; } if (!(memberDeclaration.Parent is ClassDeclarationSyntax classDeclaration)) { break; } if (classDeclaration.Identifier.ValueText.Length == 0) { break; } CodeAction codeAction = CodeAction.Create( "Rename destructor to match class name", cancellationToken => { DestructorDeclarationSyntax newNode = destructorDeclaration.WithIdentifier(classDeclaration.Identifier.WithTriviaFrom(destructorDeclaration.Identifier)); return(context.Document.ReplaceNodeAsync(destructorDeclaration, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.CannotChangeTupleElementNameWhenOverridingInheritedMember: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RenameTupleElement)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (memberDeclaration is MethodDeclarationSyntax methodDeclaration) { IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken); if (!(methodSymbol.ReturnType is INamedTypeSymbol tupleType)) { break; } if (!tupleType.IsTupleType) { break; } if (!(methodSymbol.OverriddenMethod?.ReturnType is INamedTypeSymbol baseTupleType)) { break; } if (!baseTupleType.IsTupleType) { break; } ImmutableArray <IFieldSymbol> elements = tupleType.TupleElements; ImmutableArray <IFieldSymbol> baseElements = baseTupleType.TupleElements; if (elements.Length != baseElements.Length) { break; } int i = 0; while (i < elements.Length) { if (elements[i].Name != baseElements[i].Name) { break; } i++; } if (i == elements.Length) { break; } TupleElementSyntax tupleElement = ((TupleTypeSyntax)methodDeclaration.ReturnType).Elements[i]; CodeAction codeAction = CodeAction.Create( $"Rename '{elements[i].Name}' to '{baseElements[i].Name}'", ct => RenameTupleElementAsync(context.Document, methodDeclaration, tupleElement, elements[i], baseElements[i].Name, semanticModel, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } else if (memberDeclaration is PropertyDeclarationSyntax propertyDeclaration) { IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, context.CancellationToken); if (!(propertySymbol.Type is INamedTypeSymbol tupleType)) { break; } if (!tupleType.IsTupleType) { break; } if (!(propertySymbol.OverriddenProperty?.Type is INamedTypeSymbol baseTupleType)) { break; } if (!baseTupleType.IsTupleType) { break; } ImmutableArray <IFieldSymbol> elements = tupleType.TupleElements; ImmutableArray <IFieldSymbol> baseElements = baseTupleType.TupleElements; if (elements.Length != baseElements.Length) { break; } int i = 0; while (i < elements.Length) { if (elements[i].Name != baseElements[i].Name) { break; } i++; } if (i == elements.Length) { break; } TupleElementSyntax tupleElement = ((TupleTypeSyntax)propertyDeclaration.Type).Elements[i]; CodeAction codeAction = CodeAction.Create( $"Rename '{elements[i].Name}' to '{baseElements[i].Name}'", ct => RenameTupleElementAsync(context.Document, propertyDeclaration, tupleElement, elements[i], baseElements[i].Name, semanticModel, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } break; } } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out ClassDeclarationSyntax classDeclaration)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case DiagnosticIdentifiers.MakeClassStatic: { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol symbol = semanticModel.GetDeclaredSymbol(classDeclaration, context.CancellationToken); ImmutableArray <SyntaxReference> syntaxReferences = symbol.DeclaringSyntaxReferences; if (!syntaxReferences.Any()) { break; } ModifiersCodeFixRegistrator.AddModifier( context, diagnostic, ImmutableArray.CreateRange(syntaxReferences, f => f.GetSyntax()), SyntaxKind.StaticKeyword, title: "Make class static"); break; } case DiagnosticIdentifiers.AddStaticModifierToAllPartialClassDeclarations: { ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, classDeclaration, SyntaxKind.StaticKeyword); break; } case DiagnosticIdentifiers.ImplementExceptionConstructors: { CodeAction codeAction = CodeAction.Create( "Generate exception constructors", cancellationToken => { return(ImplementExceptionConstructorsRefactoring.RefactorAsync( context.Document, classDeclaration, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseAttributeUsageAttribute: { CodeAction codeAction = CodeAction.Create( "Use AttributeUsageAttribute", cancellationToken => { return(UseAttributeUsageAttributeRefactoring.RefactorAsync( context.Document, classDeclaration, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case DiagnosticIdentifiers.FormatDeclarationBraces: { CodeAction codeAction = CodeAction.Create( "Format braces", cancellationToken => FormatDeclarationBracesRefactoring.RefactorAsync(context.Document, memberDeclaration, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.RemoveRedundantOverridingMember: { CodeAction codeAction = CodeAction.Create( $"Remove {memberDeclaration.GetTitle()}", cancellationToken => context.Document.RemoveMemberAsync(memberDeclaration, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.AddDefaultAccessModifier: { var accessibility = (Accessibility)Enum.Parse( typeof(Accessibility), context.Diagnostics[0].Properties[nameof(Accessibility)]); CodeAction codeAction = CodeAction.Create( "Add default access modifier", cancellationToken => AddDefaultAccessModifierRefactoring.RefactorAsync(context.Document, memberDeclaration, accessibility, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.AddEmptyLineBetweenDeclarations: { CodeAction codeAction = CodeAction.Create( "Add empty line", cancellationToken => AddEmptyLineBetweenDeclarationsRefactoring.RefactorAsync(context.Document, memberDeclaration, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.RemoveRedundantSealedModifier: { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, memberDeclaration, SyntaxKind.SealedKeyword); break; } case DiagnosticIdentifiers.AvoidSemicolonAtEndOfDeclaration: { CodeAction codeAction = CodeAction.Create( "Remove unnecessary semicolon", cancellationToken => AvoidSemicolonAtEndOfDeclarationRefactoring.RefactorAsync(context.Document, memberDeclaration, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.ReorderModifiers: { CodeAction codeAction = CodeAction.Create( "Reorder modifiers", cancellationToken => ReorderModifiersRefactoring.RefactorAsync(context.Document, memberDeclaration, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.MarkFieldAsReadOnly: { var fieldDeclaration = (FieldDeclarationSyntax)memberDeclaration; SeparatedSyntaxList <VariableDeclaratorSyntax> declarators = fieldDeclaration.Declaration.Variables; string title = (declarators.Count == 1) ? $"Mark '{declarators[0].Identifier.ValueText}' as read-only" : "Mark fields as read-only"; ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, fieldDeclaration, SyntaxKind.ReadOnlyKeyword, title: title); break; } case DiagnosticIdentifiers.UseConstantInsteadOfField: { CodeAction codeAction = CodeAction.Create( "Use constant instead of field", cancellationToken => UseConstantInsteadOfFieldRefactoring.RefactorAsync(context.Document, (FieldDeclarationSyntax)memberDeclaration, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseReadOnlyAutoProperty: { CodeAction codeAction = CodeAction.Create( "Use read-only auto-property", cancellationToken => UseReadOnlyAutoPropertyRefactoring.RefactorAsync(context.Document, (PropertyDeclarationSyntax)memberDeclaration, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.ReplaceCommentWithDocumentationComment: { CodeAction codeAction = CodeAction.Create( ReplaceCommentWithDocumentationCommentRefactoring.Title, cancellationToken => ReplaceCommentWithDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeAccessibility) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddStaticModifier) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveThisModifier) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassNonStatic) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveOutModifier) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveRefModifier) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddModifierAbstract)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindToken(root, context.Span.Start, out SyntaxToken token)) { return; } SyntaxNode node = token.Parent; if (!node.Kind().SupportsModifiers()) { node = node.FirstAncestor(f => f.Kind().SupportsModifiers()); } 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.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier)) { break; } SyntaxTokenList modifiers = node.GetModifiers(); 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.IndexerDeclaration)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.StaticKeyword); } else if (node.IsKind(SyntaxKind.PropertyDeclaration)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.AsyncKeyword); } break; } case CompilerDiagnosticIdentifiers.MoreThanOneProtectionModifier: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, token); } break; } case CompilerDiagnosticIdentifiers.AccessibilityModifiersMayNotBeUsedOnAccessorsInInterface: case CompilerDiagnosticIdentifiers.AccessModifiersAreNotAllowedOnStaticConstructors: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveAccessModifiers(context, diagnostic, node); } break; } case CompilerDiagnosticIdentifiers.ModifiersCannotBePlacedOnEventAccessorDeclarations: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveModifiers(context, diagnostic, node); } break; } case CompilerDiagnosticIdentifiers.OnlyMethodsClassesStructsOrInterfacesMayBePartial: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.PartialKeyword); } break; } case CompilerDiagnosticIdentifiers.ClassCannotBeBothStaticAndSealed: { if (!Settings.IsCodeFixEnabled(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.IsCodeFixEnabled(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.IsCodeFixEnabled(CodeFixIdentifiers.ChangeAccessibility)) { ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternalOrPrivate); } break; } case CompilerDiagnosticIdentifiers.VirtualOrAbstractmembersCannotBePrivate: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeAccessibility)) { ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternalOrProtected); } break; } case CompilerDiagnosticIdentifiers.AbstractPropertiesCannotHavePrivateAccessors: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveAccessModifiers(context, diagnostic, node, additionalKey: CodeFixIdentifiers.RemoveInvalidModifier); } if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeAccessibility)) { ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternalOrProtected); } break; } case CompilerDiagnosticIdentifiers.StaticMemberCannotBeMarkedOverrideVirtualOrAbstract: { if (!Settings.IsCodeFixEnabled(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.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.AsyncKeyword); } break; } case CompilerDiagnosticIdentifiers.PartialMethodCannotHaveAccessModifiersOrVirtualAbstractOverrideNewSealedOrExternModifiers: { if (!Settings.IsCodeFixEnabled(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.IsCodeFixEnabled(CodeFixIdentifiers.AddStaticModifier)) { AddStaticModifier(context, diagnostic, node, CodeFixIdentifiers.AddStaticModifier); } if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveThisModifier)) { var methodDeclaration = (MethodDeclarationSyntax)node; ParameterSyntax parameter = methodDeclaration.ParameterList.Parameters.First(); SyntaxToken modifier = parameter.Modifiers.Find(SyntaxKind.ThisKeyword); ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, parameter, modifier, additionalKey: CodeFixIdentifiers.RemoveThisModifier); } break; } case CompilerDiagnosticIdentifiers.ExtensionMethodMustBeDefinedInNonGenericStaticClass: { if (!node.IsKind(SyntaxKind.ClassDeclaration)) { return; } var classDeclaration = (ClassDeclarationSyntax)node; if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddStaticModifier) && !classDeclaration.IsStatic()) { AddStaticModifier(context, diagnostic, node, CodeFixIdentifiers.AddStaticModifier); } if (Settings.IsCodeFixEnabled(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.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.PartialKeyword); } break; } case CompilerDiagnosticIdentifiers.MethodHasParameterModifierThisWhichIsNotOnFirstParameter: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveThisModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, token.Parent, token); } break; } case CompilerDiagnosticIdentifiers.CannotDeclareInstanceMembersInStaticClass: case CompilerDiagnosticIdentifiers.StaticClassesCannotHaveInstanceConstructors: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddStaticModifier)) { AddStaticModifier(context, diagnostic, node, CodeFixIdentifiers.AddStaticModifier); } if (Settings.IsCodeFixEnabled(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.IsCodeFixEnabled(CodeFixIdentifiers.ChangeAccessibility)) { ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternal); } break; } case CompilerDiagnosticIdentifiers.NamespaceAlreadyContainsDefinition: case CompilerDiagnosticIdentifiers.TypeAlreadyContainsDefinition: { if (!Settings.IsCodeFixEnabled(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); break; } case CompilerDiagnosticIdentifiers.NoSuitableMethodFoundToOverride: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveInvalidModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.OverrideKeyword); } break; } case CompilerDiagnosticIdentifiers.AsyncMethodsCannotHaveRefOrOutParameters: case CompilerDiagnosticIdentifiers.IteratorsCannotHaveRefOrOutParameters: case CompilerDiagnosticIdentifiers.ReadOnlyFieldCannotBePassedAsRefOrOutValue: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveRefModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.RefKeyword, additionalKey: nameof(SyntaxKind.RefKeyword)); } if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveOutModifier)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.OutKeyword, additionalKey: nameof(SyntaxKind.OutKeyword)); } break; } case CompilerDiagnosticIdentifiers.CannotHaveInstancePropertyOrFieldInitializersInStruct: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddStaticModifier)) { AddStaticModifier(context, diagnostic, node); } break; } case CompilerDiagnosticIdentifiers.MemberMustDeclareBodyBecauseItIsNotMarkedAbstractExternOrPartial: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddModifierAbstract) && node.Kind() == SyntaxKind.MethodDeclaration && (node.Parent as ClassDeclarationSyntax)?.Modifiers.Contains(SyntaxKind.AbstractKeyword) == true) { ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.AbstractKeyword); } break; } } } }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindToken(root, context.Span.Start, out SyntaxToken token)) { return; } SyntaxKind kind = token.Kind(); Diagnostic diagnostic = context.Diagnostics[0]; Document document = context.Document; switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.CS0023_OperatorCannotBeAppliedToOperand: { if (kind == SyntaxKind.QuestionToken && token.Parent is ConditionalAccessExpressionSyntax conditionalAccess) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(conditionalAccess.Expression, context.CancellationToken); if (typeSymbol?.IsErrorType() == false && !typeSymbol.IsNullableType()) { if (typeSymbol.IsValueType) { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveConditionalAccess, document, root.SyntaxTree)) { CodeAction codeAction = CodeAction.Create( "Remove '?' operator", ct => document.WithTextChangeAsync(token.Span, "", ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } } else if (typeSymbol.IsReferenceType) { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddArgumentList, document, root.SyntaxTree) && conditionalAccess.WhenNotNull is MemberBindingExpressionSyntax memberBindingExpression) { ConditionalAccessExpressionSyntax newNode = conditionalAccess.WithWhenNotNull( InvocationExpression( memberBindingExpression.WithoutTrailingTrivia(), ArgumentList().WithTrailingTrivia(memberBindingExpression.GetTrailingTrivia()))); CodeAction codeAction = CodeAction.Create( "Add argument list", ct => document.ReplaceNodeAsync(conditionalAccess, newNode, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } } } } break; } case CompilerDiagnosticIdentifiers.CS0267_PartialModifierCanOnlyAppearImmediatelyBeforeClassStructInterfaceOrVoid: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.OrderModifiers, document, root.SyntaxTree)) { break; } ModifiersCodeFixRegistrator.MoveModifier(context, diagnostic, token.Parent, token); break; } case CompilerDiagnosticIdentifiers.CS1750_ValueCannotBeUsedAsDefaultParameter: { if (token.Parent is not ParameterSyntax parameter) { break; } ExpressionSyntax value = parameter.Default?.Value; if (value == null) { break; } if (value.IsKind(SyntaxKind.NullLiteralExpression)) { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue, document, root.SyntaxTree)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); CodeFixRegistrator.ReplaceNullWithDefaultValue(context, diagnostic, value, semanticModel); } } else if (!value.IsKind(SyntaxKind.DefaultExpression, SyntaxKind.DefaultLiteralExpression)) { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeParameterType, document, root.SyntaxTree)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(value, context.CancellationToken); if (!typeSymbol.IsKind(SymbolKind.ErrorType)) { CodeFixRegistrator.ChangeType(context, diagnostic, parameter.Type, typeSymbol, semanticModel); } } } break; } case CompilerDiagnosticIdentifiers.CS0126_ObjectOfTypeConvertibleToTypeIsRequired: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReturnDefaultValue, document, root.SyntaxTree)) { break; } if (!token.IsKind(SyntaxKind.ReturnKeyword)) { break; } if (!token.IsParentKind(SyntaxKind.ReturnStatement)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol symbol = semanticModel.GetEnclosingSymbol(token.SpanStart, context.CancellationToken); if (symbol == null) { break; } SymbolKind symbolKind = symbol.Kind; ITypeSymbol typeSymbol = null; if (symbolKind == SymbolKind.Method) { var methodSymbol = (IMethodSymbol)symbol; typeSymbol = methodSymbol.ReturnType; if (methodSymbol.IsAsync && (typeSymbol is INamedTypeSymbol namedTypeSymbol)) { ImmutableArray <ITypeSymbol> typeArguments = namedTypeSymbol.TypeArguments; if (typeArguments.Any()) { typeSymbol = typeArguments[0]; } } } else if (symbolKind == SymbolKind.Property) { typeSymbol = ((IPropertySymbol)symbol).Type; } else { Debug.Fail(symbolKind.ToString()); } if (typeSymbol == null) { break; } if (typeSymbol.Kind == SymbolKind.ErrorType) { break; } if (!typeSymbol.SupportsExplicitDeclaration()) { break; } var returnStatement = (ReturnStatementSyntax)token.Parent; CodeAction codeAction = CodeAction.Create( "Return default value", ct => { ExpressionSyntax expression = typeSymbol.GetDefaultValueSyntax(document.GetDefaultSyntaxOptions()); if (expression.IsKind(SyntaxKind.DefaultExpression) && document.SupportsLanguageFeature(CSharpLanguageFeature.DefaultLiteral)) { expression = CSharpFactory.DefaultLiteralExpression().WithTriviaFrom(expression); } ReturnStatementSyntax newNode = returnStatement.WithExpression(expression); return(document.ReplaceNodeAsync(returnStatement, newNode, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.CS1031_TypeExpected: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddMissingType, document, root.SyntaxTree)) { break; } if (!token.IsKind(SyntaxKind.CloseParenToken)) { break; } if (token.Parent is not DefaultExpressionSyntax defaultExpression) { break; } if (defaultExpression.Type is not IdentifierNameSyntax identifierName) { break; } if (!identifierName.IsMissing) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); TypeInfo typeInfo = semanticModel.GetTypeInfo(defaultExpression, context.CancellationToken); ITypeSymbol convertedType = typeInfo.ConvertedType; if (convertedType?.SupportsExplicitDeclaration() != true) { break; } CodeAction codeAction = CodeAction.Create( $"Add type '{SymbolDisplay.ToMinimalDisplayString(convertedType, semanticModel, defaultExpression.SpanStart, SymbolDisplayFormats.DisplayName)}'", ct => { TypeSyntax newType = convertedType.ToTypeSyntax() .WithTriviaFrom(identifierName) .WithFormatterAndSimplifierAnnotation(); return(document.ReplaceNodeAsync(identifierName, newType, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.CS1597_SemicolonAfterMethodOrAccessorBlockIsNotValid: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveSemicolon, document, root.SyntaxTree)) { break; } if (!token.IsKind(SyntaxKind.SemicolonToken)) { break; } switch (token.Parent) { case MethodDeclarationSyntax methodDeclaration: { BlockSyntax body = methodDeclaration.Body; if (body == null) { break; } CodeAction codeAction = CodeAction.Create( "Remove semicolon", ct => { SyntaxTriviaList trivia = body .GetTrailingTrivia() .EmptyIfWhitespace() .AddRange(token.LeadingTrivia.EmptyIfWhitespace()) .AddRange(token.TrailingTrivia); MethodDeclarationSyntax newNode = methodDeclaration .WithBody(body.WithTrailingTrivia(trivia)) .WithSemicolonToken(default(SyntaxToken)); return(document.ReplaceNodeAsync(methodDeclaration, newNode, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case PropertyDeclarationSyntax propertyDeclaration: { AccessorListSyntax accessorList = propertyDeclaration.AccessorList; if (accessorList == null) { break; } CodeAction codeAction = CodeAction.Create( "Remove semicolon", ct => { SyntaxTriviaList trivia = accessorList .GetTrailingTrivia() .EmptyIfWhitespace() .AddRange(token.LeadingTrivia.EmptyIfWhitespace()) .AddRange(token.TrailingTrivia); PropertyDeclarationSyntax newNode = propertyDeclaration .WithAccessorList(accessorList.WithTrailingTrivia(trivia)) .WithSemicolonToken(default(SyntaxToken)); return(document.ReplaceNodeAsync(propertyDeclaration, newNode, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case AccessorDeclarationSyntax accessorDeclaration: { BlockSyntax body = accessorDeclaration.Body; if (body == null) { break; } CodeAction codeAction = CodeAction.Create( "Remove semicolon", ct => { SyntaxTriviaList trivia = body .GetTrailingTrivia() .EmptyIfWhitespace() .AddRange(token.LeadingTrivia.EmptyIfWhitespace()) .AddRange(token.TrailingTrivia); AccessorDeclarationSyntax newNode = accessorDeclaration .WithBody(body.WithTrailingTrivia(trivia)) .WithSemicolonToken(default(SyntaxToken)); return(document.ReplaceNodeAsync(accessorDeclaration, newNode, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } break; } case CompilerDiagnosticIdentifiers.CS0030_CannotConvertType: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeForEachType, document, root.SyntaxTree)) { break; } if (!token.IsKind(SyntaxKind.ForEachKeyword)) { break; } if (token.Parent is not ForEachStatementSyntax forEachStatement) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ForEachStatementInfo info = semanticModel.GetForEachStatementInfo(forEachStatement); ITypeSymbol typeSymbol = info.ElementType; if (typeSymbol.SupportsExplicitDeclaration()) { CodeFixRegistrator.ChangeType(context, diagnostic, forEachStatement.Type, typeSymbol, semanticModel, CodeFixIdentifiers.ChangeForEachType); } CodeFixRegistrator.ChangeTypeToVar(context, diagnostic, forEachStatement.Type, CodeFixIdentifiers.ChangeTypeToVar); break; } case CompilerDiagnosticIdentifiers.CS1737_OptionalParametersMustAppearAfterAllRequiredParameters: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddDefaultValueToParameter, document, root.SyntaxTree)) { break; } if (token.Parent is not BaseParameterListSyntax parameterList) { break; } SeparatedSyntaxList <ParameterSyntax> parameters = parameterList.Parameters; ParameterSyntax parameter = null; for (int i = 0; i < parameters.Count; i++) { ParameterSyntax p = parameters[i]; if (p.FullSpan.End <= token.SpanStart) { parameter = p; } else { break; } } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); IParameterSymbol parameterSymbol = semanticModel.GetDeclaredSymbol(parameter, context.CancellationToken); ITypeSymbol typeSymbol = parameterSymbol.Type; if (typeSymbol.Kind == SymbolKind.ErrorType) { break; } CodeAction codeAction = CodeAction.Create( "Add default value", ct => { ExpressionSyntax defaultValue = typeSymbol.GetDefaultValueSyntax(document.GetDefaultSyntaxOptions()); ParameterSyntax newParameter = parameter .WithDefault(EqualsValueClause(defaultValue).WithTrailingTrivia(parameter.GetTrailingTrivia())) .WithoutTrailingTrivia() .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(parameter, newParameter, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.CS8632_AnnotationForNullableReferenceTypesShouldOnlyBeUsedWithinNullableAnnotationsContext: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveAnnotationForNullableReferenceTypes, document, root.SyntaxTree)) { break; } if (!token.IsKind(SyntaxKind.QuestionToken)) { return; } CodeAction codeAction = CodeAction.Create( "Remove 'nullable' annotation", ct => { var textChange = new TextChange(token.Span, ""); return(document.WithTextChangeAsync(textChange, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.CS8602_DereferenceOfPossiblyNullReference: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseNullForgivingOperator, document, root.SyntaxTree)) { break; } Debug.Assert(token.IsKind(SyntaxKind.IdentifierToken), token.Kind().ToString()); if (!token.IsKind(SyntaxKind.IdentifierToken)) { return; } if (!token.IsParentKind(SyntaxKind.IdentifierName)) { return; } SyntaxNode node = token.Parent .WalkUp(f => f.IsKind(SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.InvocationExpression, SyntaxKind.ElementAccessExpression)) .Parent; if (node.IsKind(SyntaxKind.ExpressionStatement) && token.SpanStart == node.SpanStart) { CodeAction codeAction = CodeAction.Create( "Use null propagation operator", ct => { var textChange = new TextChange(new TextSpan(token.Span.End, 0), "?"); return(document.WithTextChangeAsync(textChange, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } return; } case CompilerDiagnosticIdentifiers.CS8604_PossibleNullReferenceArgumentForParameter: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseNullForgivingOperator, document, root.SyntaxTree)) { break; } Debug.Assert(token.IsKind(SyntaxKind.IdentifierToken), token.Kind().ToString()); if (!token.IsKind(SyntaxKind.IdentifierToken)) { return; } if (!token.IsParentKind(SyntaxKind.IdentifierName)) { return; } CodeAction codeAction = CodeAction.Create( "Use null-forgiving operator", ct => { var identifierName = (IdentifierNameSyntax)token.Parent; PostfixUnaryExpressionSyntax newExpression = SuppressNullableWarningExpression(identifierName.WithoutTrivia()) .WithTriviaFrom(identifierName); return(document.ReplaceNodeAsync(identifierName, newExpression, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); return; } case CompilerDiagnosticIdentifiers.CS8618_NonNullableMemberIsUninitialized: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseNullForgivingOperator, document, root.SyntaxTree)) { break; } Debug.Assert(token.IsKind(SyntaxKind.IdentifierToken), token.Kind().ToString()); if (!token.IsKind(SyntaxKind.IdentifierToken)) { return; } if (token.IsParentKind(SyntaxKind.PropertyDeclaration)) { CodeAction codeAction = CodeAction.Create( "Use null-forgiving operator", ct => { var property = (PropertyDeclarationSyntax)token.Parent; PropertyDeclarationSyntax newProperty = property .WithoutTrailingTrivia() .WithInitializer(EqualsValueClause(SuppressNullableWarningExpression(NullLiteralExpression()))) .WithSemicolonToken(SemicolonToken().WithTrailingTrivia(property.GetTrailingTrivia())); return(document.ReplaceNodeAsync(property, newProperty, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } else { SyntaxDebug.Assert( (token.IsParentKind(SyntaxKind.VariableDeclarator) && token.Parent.IsParentKind(SyntaxKind.VariableDeclaration) && token.Parent.Parent.IsParentKind(SyntaxKind.FieldDeclaration, SyntaxKind.EventFieldDeclaration)) || token.IsParentKind(SyntaxKind.ConstructorDeclaration), token); if (token.IsParentKind(SyntaxKind.VariableDeclarator) && token.Parent.IsParentKind(SyntaxKind.VariableDeclaration) && token.Parent.Parent.IsParentKind(SyntaxKind.FieldDeclaration)) { CodeAction codeAction = CodeAction.Create( "Use null-forgiving operator", ct => { var declarator = (VariableDeclaratorSyntax)token.Parent; VariableDeclaratorSyntax newDeclarator = declarator .WithoutTrailingTrivia() .WithInitializer( EqualsValueClause(SuppressNullableWarningExpression(NullLiteralExpression())) .WithTrailingTrivia(declarator.GetTrailingTrivia())); return(document.ReplaceNodeAsync(declarator, newDeclarator, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } } break; } case CompilerDiagnosticIdentifiers.CS8403_MethodWithIteratorBlockMustBeAsyncToReturnIAsyncEnumerableOfT: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddAsyncModifier, document, root.SyntaxTree)) { break; } SyntaxDebug.Assert(token.IsKind(SyntaxKind.IdentifierToken), token); SyntaxDebug.Assert(token.IsParentKind(SyntaxKind.MethodDeclaration, SyntaxKind.LocalFunctionStatement), token.Parent); if (token.IsParentKind(SyntaxKind.MethodDeclaration, SyntaxKind.LocalFunctionStatement)) { ModifiersCodeFixRegistrator.AddModifier( context, diagnostic, token.Parent, SyntaxKind.AsyncKeyword, additionalKey: CodeFixIdentifiers.AddAsyncModifier); } break; } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddDocumentationComment) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveParametersFromStaticConstructor) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveMemberDeclaration)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.MissingXmlCommentForPubliclyVisibleTypeOrMember: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddDocumentationComment)) { break; } CodeAction codeAction = CodeAction.Create( "Add documentation comment", cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, false, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); CodeAction codeAction2 = CodeAction.Create( "Add documentation comment (copy from base if available)", cancellationToken => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, true, cancellationToken), GetEquivalenceKey(diagnostic, "CopyFromBaseIfAvailable")); context.RegisterCodeFix(codeAction2, diagnostic); break; } case CompilerDiagnosticIdentifiers.MethodReturnTypeMustMatchOverriddenMethodReturnType: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); ITypeSymbol typeSymbol = methodSymbol.OverriddenMethod.ReturnType; if (typeSymbol?.IsErrorType() == false) { CodeAction codeAction = CodeAction.Create( $"Change return type to '{SymbolDisplay.GetMinimalString(typeSymbol, semanticModel, memberDeclaration.SpanStart)}'", cancellationToken => MemberTypeMustMatchOverriddenMemberTypeRefactoring.RefactorAsync(context.Document, memberDeclaration, typeSymbol, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } break; } case CompilerDiagnosticIdentifiers.PartialMethodsMustHaveVoidReturnType: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var methodDeclaration = (MethodDeclarationSyntax)memberDeclaration; MethodDeclarationSyntax otherPart = semanticModel.GetOtherPart(methodDeclaration, context.CancellationToken); if (otherPart == null) { break; } CodeAction codeAction = CodeAction.Create( "Change return type to 'void'", cancellationToken => { return(context.Document.Solution().ReplaceNodesAsync( new MethodDeclarationSyntax[] { methodDeclaration, otherPart }, (node, rewrittenNode) => node.WithReturnType(CSharpFactory.VoidType().WithTriviaFrom(node.ReturnType)), cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.MemberTypeMustMatchOverriddenMemberType: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ITypeSymbol typeSymbol = null; switch (memberDeclaration.Kind()) { case SyntaxKind.PropertyDeclaration: case SyntaxKind.IndexerDeclaration: { var propertySymbol = (IPropertySymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); typeSymbol = propertySymbol.OverriddenProperty.Type; break; } case SyntaxKind.EventDeclaration: { var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); typeSymbol = eventSymbol.OverriddenEvent.Type; break; } case SyntaxKind.EventFieldDeclaration: { VariableDeclaratorSyntax declarator = ((EventFieldDeclarationSyntax)memberDeclaration).Declaration.Variables.First(); var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(declarator, context.CancellationToken); typeSymbol = eventSymbol.OverriddenEvent.Type; break; } } if (typeSymbol?.IsErrorType() == false) { string title = $"Change type to '{SymbolDisplay.GetMinimalString(typeSymbol, semanticModel, memberDeclaration.SpanStart)}'"; CodeAction codeAction = CodeAction.Create( title, cancellationToken => MemberTypeMustMatchOverriddenMemberTypeRefactoring.RefactorAsync(context.Document, memberDeclaration, typeSymbol, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } break; } case CompilerDiagnosticIdentifiers.MissingPartialModifier: case CompilerDiagnosticIdentifiers.PartialMethodMustBeDeclaredWithinPartialClassOrPartialStruct: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier)) { break; } SyntaxNode node = null; switch (memberDeclaration.Kind()) { case SyntaxKind.MethodDeclaration: { if (memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration)) { node = memberDeclaration.Parent; } break; } case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: { node = memberDeclaration; break; } } Debug.Assert(node != null, memberDeclaration.ToString()); if (node == null) { break; } ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.PartialKeyword); break; } case CompilerDiagnosticIdentifiers.MemberIsAbstractButItIsContainedInNonAbstractClass: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract)) { break; } if (!memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration)) { break; } ModifiersCodeFixRegistrator.AddModifier( context, diagnostic, memberDeclaration.Parent, SyntaxKind.AbstractKeyword, title: "Make containing class abstract"); break; } case CompilerDiagnosticIdentifiers.StaticConstructorMustBeParameterless: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveParametersFromStaticConstructor)) { break; } var constructorDeclaration = (ConstructorDeclarationSyntax)memberDeclaration; CodeAction codeAction = CodeAction.Create( "Remove parameters", cancellationToken => { ParameterListSyntax parameterList = constructorDeclaration.ParameterList; ParameterListSyntax newParameterList = parameterList .WithParameters(default(SeparatedSyntaxList <ParameterSyntax>)) .WithOpenParenToken(parameterList.OpenParenToken.WithoutTrailingTrivia()) .WithCloseParenToken(parameterList.CloseParenToken.WithoutLeadingTrivia()); ConstructorDeclarationSyntax newNode = constructorDeclaration.WithParameterList(newParameterList); return(context.Document.ReplaceNodeAsync(constructorDeclaration, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.ExplicitInterfaceDeclarationCanOnlyBeDeclaredInClassOrStruct: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveMemberDeclaration)) { break; } CodeFixRegistrator.RemoveMember(context, diagnostic, memberDeclaration); break; } } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsAnyEnabled( CodeFixIdentifiers.WrapInUnsafeStatement, CodeFixIdentifiers.MakeContainingDeclarationUnsafe)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindNode(root, context.Span, out SyntaxNode node)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.PointersAndFixedSizeBuffersMayOnlyBeUsedInUnsafeContext: { bool fStatement = false; bool fMemberDeclaration = false; foreach (SyntaxNode ancestor in node.AncestorsAndSelf()) { if (fStatement && fMemberDeclaration) { break; } if (!fStatement && ancestor is StatementSyntax) { fStatement = true; if (!Settings.IsEnabled(CodeFixIdentifiers.WrapInUnsafeStatement)) { continue; } var statement = (StatementSyntax)ancestor; if (statement.IsKind(SyntaxKind.Block) && statement.Parent is StatementSyntax) { statement = (StatementSyntax)statement.Parent; } if (statement.IsKind(SyntaxKind.UnsafeStatement)) { break; } CodeAction codeAction = CodeAction.Create( "Wrap in unsafe block", cancellationToken => { BlockSyntax block = (statement.IsKind(SyntaxKind.Block)) ? (BlockSyntax)statement : SyntaxFactory.Block(statement); UnsafeStatementSyntax unsafeStatement = SyntaxFactory.UnsafeStatement(block).WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(statement, unsafeStatement, cancellationToken)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.WrapInUnsafeStatement)); context.RegisterCodeFix(codeAction, diagnostic); } else if (!fMemberDeclaration && ancestor is MemberDeclarationSyntax) { fMemberDeclaration = true; if (!Settings.IsEnabled(CodeFixIdentifiers.MakeContainingDeclarationUnsafe)) { continue; } if (!CSharpFacts.CanHaveModifiers(ancestor.Kind())) { continue; } ModifiersCodeFixRegistrator.AddModifier( context, diagnostic, ancestor, SyntaxKind.UnsafeKeyword, title: "Make containing declaration unsafe", additionalKey: CodeFixIdentifiers.MakeContainingDeclarationUnsafe); } } break; } } } }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case DiagnosticIdentifiers.RemoveRedundantOverridingMember: { CodeAction codeAction = CodeActionFactory.RemoveMemberDeclaration(context.Document, memberDeclaration, equivalenceKey: GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.AddAccessibilityModifiersOrViceVersa: { if (diagnostic.Properties.TryGetValue(nameof(Accessibility), out string accessibilityText)) { var accessibility = (Accessibility)Enum.Parse(typeof(Accessibility), accessibilityText); CodeAction codeAction = CodeAction.Create( "Add accessibility modifiers", ct => { MemberDeclarationSyntax newNode = SyntaxAccessibility.WithExplicitAccessibility(memberDeclaration, accessibility); return(context.Document.ReplaceNodeAsync(memberDeclaration, newNode, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } else { CodeAction codeAction = CodeAction.Create( "Remove accessibility modifiers", ct => { MemberDeclarationSyntax newNode = SyntaxAccessibility.WithoutExplicitAccessibility(memberDeclaration); return(context.Document.ReplaceNodeAsync(memberDeclaration, newNode, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } break; } case DiagnosticIdentifiers.RemoveRedundantSealedModifier: { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, memberDeclaration, SyntaxKind.SealedKeyword); break; } case DiagnosticIdentifiers.AvoidSemicolonAtEndOfDeclaration: { CodeAction codeAction = CodeAction.Create( "Remove unnecessary semicolon", cancellationToken => AvoidSemicolonAtEndOfDeclarationRefactoring.RefactorAsync(context.Document, memberDeclaration, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.OrderModifiers: { CodeAction codeAction = CodeAction.Create( "Order modifiers", ct => OrderModifiersAsync(context.Document, memberDeclaration, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.MakeFieldReadOnly: { var fieldDeclaration = (FieldDeclarationSyntax)memberDeclaration; SeparatedSyntaxList <VariableDeclaratorSyntax> declarators = fieldDeclaration.Declaration.Variables; string title = (declarators.Count == 1) ? $"Make '{declarators[0].Identifier.ValueText}' read-only" : "Make fields read-only"; ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, fieldDeclaration, SyntaxKind.ReadOnlyKeyword, title: title); break; } case DiagnosticIdentifiers.UseConstantInsteadOfField: { CodeAction codeAction = CodeAction.Create( "Use constant instead of field", cancellationToken => UseConstantInsteadOfFieldRefactoring.RefactorAsync(context.Document, (FieldDeclarationSyntax)memberDeclaration, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.UseReadOnlyAutoProperty: { CodeAction codeAction = CodeAction.Create( "Use read-only auto-property", cancellationToken => UseReadOnlyAutoPropertyAsync(context.Document, (PropertyDeclarationSyntax)memberDeclaration, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.ConvertCommentToDocumentationComment: { CodeAction codeAction = CodeAction.Create( ConvertCommentToDocumentationCommentRefactoring.Title, cancellationToken => ConvertCommentToDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, context.Span, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case DiagnosticIdentifiers.MakeMethodExtensionMethod: { var methodDeclaration = (MethodDeclarationSyntax)memberDeclaration; CodeAction codeAction = CodeAction.Create( "Make method an extension method", cancellationToken => { ParameterSyntax parameter = methodDeclaration.ParameterList.Parameters[0]; ParameterSyntax newParameter = ModifierList.Insert(parameter, SyntaxKind.ThisKeyword); return(context.Document.ReplaceNodeAsync(parameter, newParameter, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindNode(root, context.Span, out SyntaxNode node)) { return; } Document document = context.Document; foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.CS0214_PointersAndFixedSizeBuffersMayOnlyBeUsedInUnsafeContext: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseExplicitTypeInsteadOfVar, document, root.SyntaxTree) && node is StackAllocArrayCreationExpressionSyntax stackAllocArrayCreation && node.IsParentKind(SyntaxKind.EqualsValueClause) && node.Parent.IsParentKind(SyntaxKind.VariableDeclarator) && node.Parent.Parent.Parent is VariableDeclarationSyntax variableDeclaration && variableDeclaration.Type.IsVar) { TypeSyntax type = stackAllocArrayCreation.Type; if (type is ArrayTypeSyntax arrayType) { type = arrayType.ElementType; } CodeAction spanCodeAction = CodeAction.Create( "Use Span<T>", ct => { TypeSyntax spanOfT = SyntaxFactory.ParseTypeName($"global::System.Span<{type}>") .WithSimplifierAnnotation(); return(document.ReplaceNodeAsync(variableDeclaration.Type, spanOfT, ct)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.UseExplicitTypeInsteadOfVar, "System_Span_T")); context.RegisterCodeFix(spanCodeAction, diagnostic); CodeAction readOnlySpanCodeAction = CodeAction.Create( "Use ReadOnlySpan<T>", ct => { TypeSyntax spanOfT = SyntaxFactory.ParseTypeName($"global::System.ReadOnlySpan<{type}>") .WithSimplifierAnnotation(); return(document.ReplaceNodeAsync(variableDeclaration.Type, spanOfT, ct)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.UseExplicitTypeInsteadOfVar, "System_ReadOnlySpan_T")); context.RegisterCodeFix(readOnlySpanCodeAction, diagnostic); } var fStatement = false; var fMemberDeclaration = false; foreach (SyntaxNode ancestor in node.AncestorsAndSelf()) { if (fStatement && fMemberDeclaration) { break; } if (!fStatement && ancestor is StatementSyntax) { fStatement = true; if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.WrapInUnsafeStatement, document, root.SyntaxTree)) { continue; } var statement = (StatementSyntax)ancestor; if (statement.IsKind(SyntaxKind.Block) && statement.Parent is StatementSyntax statement2) { statement = statement2; } if (statement.IsKind(SyntaxKind.UnsafeStatement)) { break; } CodeAction codeAction = CodeAction.Create( "Wrap in unsafe block", ct => { BlockSyntax block = (statement.IsKind(SyntaxKind.Block)) ? (BlockSyntax)statement : SyntaxFactory.Block(statement); UnsafeStatementSyntax unsafeStatement = SyntaxFactory.UnsafeStatement(block).WithFormatterAnnotation(); return(document.ReplaceNodeAsync(statement, unsafeStatement, ct)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.WrapInUnsafeStatement)); context.RegisterCodeFix(codeAction, diagnostic); } else if (!fMemberDeclaration && ancestor is MemberDeclarationSyntax) { fMemberDeclaration = true; if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeContainingDeclarationUnsafe, document, root.SyntaxTree)) { continue; } if (!CSharpFacts.CanHaveModifiers(ancestor.Kind())) { continue; } ModifiersCodeFixRegistrator.AddModifier( context, diagnostic, ancestor, SyntaxKind.UnsafeKeyword, title: "Make containing declaration unsafe", additionalKey: CodeFixIdentifiers.MakeContainingDeclarationUnsafe); } } break; } } } }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.CS1591_MissingXmlCommentForPubliclyVisibleTypeOrMember: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddDocumentationComment, context.Document, root.SyntaxTree)) { break; } CodeAction codeAction = CodeAction.Create( "Add documentation comment", ct => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, false, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); CodeAction codeAction2 = CodeAction.Create( "Add documentation comment (copy from base if available)", ct => AddDocumentationCommentRefactoring.RefactorAsync(context.Document, memberDeclaration, true, ct), GetEquivalenceKey(diagnostic, "CopyFromBaseIfAvailable")); context.RegisterCodeFix(codeAction2, diagnostic); break; } case CompilerDiagnosticIdentifiers.CS0508_MethodReturnTypeMustMatchOverriddenMethodReturnType: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeMethodReturnType, context.Document, root.SyntaxTree)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); ITypeSymbol typeSymbol = methodSymbol.OverriddenMethod.ReturnType; CodeFixRegistrator.ChangeTypeOrReturnType(context, diagnostic, memberDeclaration, typeSymbol, semanticModel); break; } case CompilerDiagnosticIdentifiers.CS0766_PartialMethodsMustHaveVoidReturnType: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeMethodReturnType, context.Document, root.SyntaxTree)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var methodDeclaration = (MethodDeclarationSyntax)memberDeclaration; MethodDeclarationSyntax otherPart = semanticModel.GetOtherPart(methodDeclaration, context.CancellationToken); if (otherPart == null) { break; } CodeAction codeAction = CodeAction.Create( "Change return type to 'void'", ct => { return(context.Document.Solution().ReplaceNodesAsync( new MethodDeclarationSyntax[] { methodDeclaration, otherPart }, (node, _) => node.WithReturnType(CSharpFactory.VoidType().WithTriviaFrom(node.ReturnType)), ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.CS1715_MemberTypeMustMatchOverriddenMemberType: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType, context.Document, root.SyntaxTree)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ITypeSymbol typeSymbol = null; switch (memberDeclaration.Kind()) { case SyntaxKind.PropertyDeclaration: case SyntaxKind.IndexerDeclaration: { var propertySymbol = (IPropertySymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); typeSymbol = propertySymbol.OverriddenProperty.Type; break; } case SyntaxKind.EventDeclaration: { var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); typeSymbol = eventSymbol.OverriddenEvent.Type; break; } case SyntaxKind.EventFieldDeclaration: { VariableDeclaratorSyntax declarator = ((EventFieldDeclarationSyntax)memberDeclaration).Declaration.Variables[0]; var eventSymbol = (IEventSymbol)semanticModel.GetDeclaredSymbol(declarator, context.CancellationToken); typeSymbol = eventSymbol.OverriddenEvent.Type; break; } } CodeFixRegistrator.ChangeTypeOrReturnType(context, diagnostic, memberDeclaration, typeSymbol, semanticModel); break; } case CompilerDiagnosticIdentifiers.CS0260_MissingPartialModifier: case CompilerDiagnosticIdentifiers.CS0751_PartialMethodMustBeDeclaredInPartialClassOrPartialStruct: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddPartialModifier, context.Document, root.SyntaxTree)) { break; } SyntaxNode node = null; switch (memberDeclaration.Kind()) { case SyntaxKind.MethodDeclaration: { if (memberDeclaration.IsParentKind( SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration, SyntaxKind.RecordDeclaration, SyntaxKind.RecordStructDeclaration)) { node = memberDeclaration.Parent; } break; } case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.RecordStructDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.RecordDeclaration: { node = memberDeclaration; break; } } SyntaxDebug.Assert(node != null, memberDeclaration); if (node == null) { break; } ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.PartialKeyword, title: $"Make {CSharpFacts.GetTitle(node)} partial"); break; } case CompilerDiagnosticIdentifiers.CS0513_MemberIsAbstractButItIsContainedInNonAbstractClass: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeContainingClassAbstract, context.Document, root.SyntaxTree)) { break; } if (!memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration)) { break; } ModifiersCodeFixRegistrator.AddModifier( context, diagnostic, memberDeclaration.Parent, SyntaxKind.AbstractKeyword, title: "Make containing class abstract"); break; } case CompilerDiagnosticIdentifiers.CS0132_StaticConstructorMustBeParameterless: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveParametersFromStaticConstructor, context.Document, root.SyntaxTree)) { break; } var constructorDeclaration = (ConstructorDeclarationSyntax)memberDeclaration; CodeAction codeAction = CodeAction.Create( "Remove parameters", ct => { ParameterListSyntax parameterList = constructorDeclaration.ParameterList; ParameterListSyntax newParameterList = parameterList .WithParameters(default(SeparatedSyntaxList <ParameterSyntax>)) .WithOpenParenToken(parameterList.OpenParenToken.WithoutTrailingTrivia()) .WithCloseParenToken(parameterList.CloseParenToken.WithoutLeadingTrivia()); ConstructorDeclarationSyntax newNode = constructorDeclaration.WithParameterList(newParameterList); return(context.Document.ReplaceNodeAsync(constructorDeclaration, newNode, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.CS0541_ExplicitInterfaceDeclarationCanOnlyBeDeclaredInClassOrStruct: case CompilerDiagnosticIdentifiers.CS0525_InterfacesCannotContainFields: case CompilerDiagnosticIdentifiers.CS0567_InterfacesCannotContainOperators: case CompilerDiagnosticIdentifiers.CS0524_InterfacesCannotDeclareTypes: case CompilerDiagnosticIdentifiers.CS0575_OnlyClassTypesCanContainDestructors: case CompilerDiagnosticIdentifiers.CS0568_StructsCannotContainExplicitParameterlessConstructors: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveMemberDeclaration, context.Document, root.SyntaxTree)) { break; } CodeFixRegistrator.RemoveMemberDeclaration(context, diagnostic, memberDeclaration); break; } case CompilerDiagnosticIdentifiers.CS0574_NameOfDestructorMustMatchNameOfClass: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RenameDestructorToMatchClassName, context.Document, root.SyntaxTree)) { break; } if (memberDeclaration is not DestructorDeclarationSyntax destructorDeclaration) { break; } if (memberDeclaration.Parent is not ClassDeclarationSyntax classDeclaration) { break; } if (classDeclaration.Identifier.ValueText.Length == 0) { break; } CodeAction codeAction = CodeAction.Create( "Rename destructor to match class name", ct => { DestructorDeclarationSyntax newNode = destructorDeclaration.WithIdentifier(classDeclaration.Identifier.WithTriviaFrom(destructorDeclaration.Identifier)); return(context.Document.ReplaceNodeAsync(destructorDeclaration, newNode, ct)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.CS8139_CannotChangeTupleElementNameWhenOverridingInheritedMember: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RenameTupleElement, context.Document, root.SyntaxTree)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (memberDeclaration is MethodDeclarationSyntax methodDeclaration) { IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken); if (methodSymbol.ReturnType is not INamedTypeSymbol tupleType) { break; } if (!tupleType.IsTupleType) { break; } if (methodSymbol.OverriddenMethod?.ReturnType is not INamedTypeSymbol baseTupleType) { break; } if (!baseTupleType.IsTupleType) { break; } ImmutableArray <IFieldSymbol> elements = tupleType.TupleElements; ImmutableArray <IFieldSymbol> baseElements = baseTupleType.TupleElements; if (elements.Length != baseElements.Length) { break; } int i = 0; while (i < elements.Length) { if (elements[i].Name != baseElements[i].Name) { break; } i++; } if (i == elements.Length) { break; } TupleElementSyntax tupleElement = ((TupleTypeSyntax)methodDeclaration.ReturnType).Elements[i]; CodeAction codeAction = CodeAction.Create( $"Rename '{elements[i].Name}' to '{baseElements[i].Name}'", ct => RenameTupleElementAsync(context.Document, methodDeclaration, tupleElement, elements[i], baseElements[i].Name, semanticModel, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } else if (memberDeclaration is PropertyDeclarationSyntax propertyDeclaration) { IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, context.CancellationToken); if (propertySymbol.Type is not INamedTypeSymbol tupleType) { break; } if (!tupleType.IsTupleType) { break; } if (propertySymbol.OverriddenProperty?.Type is not INamedTypeSymbol baseTupleType) { break; } if (!baseTupleType.IsTupleType) { break; } ImmutableArray <IFieldSymbol> elements = tupleType.TupleElements; ImmutableArray <IFieldSymbol> baseElements = baseTupleType.TupleElements; if (elements.Length != baseElements.Length) { break; } int i = 0; while (i < elements.Length) { if (elements[i].Name != baseElements[i].Name) { break; } i++; } if (i == elements.Length) { break; } TupleElementSyntax tupleElement = ((TupleTypeSyntax)propertyDeclaration.Type).Elements[i]; CodeAction codeAction = CodeAction.Create( $"Rename '{elements[i].Name}' to '{baseElements[i].Name}'", ct => RenameTupleElementAsync(context.Document, propertyDeclaration, tupleElement, elements[i], baseElements[i].Name, semanticModel, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } break; } case CompilerDiagnosticIdentifiers.CS3000_MethodsWithVariableArgumentsAreNotCLSCompliant: case CompilerDiagnosticIdentifiers.CS3001_ArgumentTypeIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.CS3002_ReturnTypeIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.CS3003_TypeOfVariableIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.CS3005_IdentifierDifferingOnlyInCaseIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.CS3006_OverloadedMethodDifferingOnlyInRefOrOutOrInArrayRankIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.CS3007_OverloadedMethodDifferingOnlyByUnnamedArrayTypesIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.CS3008_IdentifierIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.CS3009_BaseTypeIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.CS3016_ArraysAsAttributeArgumentsIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.CS3024_ConstraintTypeIsNotCLSCompliant: case CompilerDiagnosticIdentifiers.CS3027_TypeIsNotCLSCompliantBecauseBaseInterfaceIsNotCLSCompliant: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.MarkDeclarationAsNonCLSCompliant, context.Document, root.SyntaxTree)) { break; } CodeAction codeAction = CodeAction.Create( $"Mark {CSharpFacts.GetTitle(memberDeclaration)} as non-CLS-compliant", ct => MarkDeclarationAsNonCLSCompliantAsync(context.Document, memberDeclaration, ct), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.CS0539_ExplicitInterfaceDeclarationIsNotMemberOfInterface: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddParameterToExplicitlyImplementedInterfaceMember, context.Document, root.SyntaxTree)) { break; } var context2 = new CommonFixContext( context.Document, GetEquivalenceKey(diagnostic), await context.GetSemanticModelAsync().ConfigureAwait(false), context.CancellationToken); CodeAction codeAction = AddParameterToInterfaceMemberRefactoring.ComputeRefactoringForExplicitImplementation(context2, memberDeclaration); if (codeAction != null) { context.RegisterCodeFix(codeAction, diagnostic); } break; } } } }
public 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.CS0106_ModifierIsNotValidForThisItem: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier, context.Document, root.SyntaxTree)) { 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, SyntaxKind.RecordStructDeclaration) && 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.CS0107_MoreThanOneProtectionModifier: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, token); } break; } case CompilerDiagnosticIdentifiers.CS0275_AccessibilityModifiersMayNotBeUsedOnAccessorsInInterface: case CompilerDiagnosticIdentifiers.CS0515_AccessModifiersAreNotAllowedOnStaticConstructors: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.RemoveAccessibility(context, diagnostic, node); } break; } case CompilerDiagnosticIdentifiers.CS1609_ModifiersCannotBePlacedOnEventAccessorDeclarations: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.RemoveModifiers(context, diagnostic, node); } break; } case CompilerDiagnosticIdentifiers.CS0753_OnlyMethodsClassesStructsOrInterfacesMayBePartial: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.PartialKeyword); } break; } case CompilerDiagnosticIdentifiers.CS0441_ClassCannotBeBothStaticAndSealed: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier, context.Document, root.SyntaxTree)) { 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.CS0678_FieldCanNotBeBothVolatileAndReadOnly: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier, context.Document, root.SyntaxTree)) { 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.CS0628_NewProtectedMemberDeclaredInSealedClass: case CompilerDiagnosticIdentifiers.CS1057_StaticClassesCannotContainProtectedMembers: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeAccessibility, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternalOrPrivate); } break; } case CompilerDiagnosticIdentifiers.CS0621_VirtualOrAbstractMembersCannotBePrivate: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveVirtualModifier, context.Document, root.SyntaxTree)) { ModifierListInfo modifierInfo = SyntaxInfo.ModifierListInfo(node); if (modifierInfo.IsVirtual) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.VirtualKeyword, additionalKey: nameof(SyntaxKind.VirtualKeyword)); } } if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeAccessibility, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternalOrProtected); } break; } case CompilerDiagnosticIdentifiers.CS0442_AbstractPropertiesCannotHavePrivateAccessors: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.RemoveAccessibility(context, diagnostic, node, additionalKey: CodeFixIdentifiers.RemoveInvalidModifier); } if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeAccessibility, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternalOrProtected); } break; } case CompilerDiagnosticIdentifiers.CS0112_StaticMemberCannotBeMarkedOverrideVirtualOrAbstract: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier, context.Document, root.SyntaxTree)) { 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.CS1994_AsyncModifierCanOnlyBeUsedInMethodsThatHaveBody: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.AsyncKeyword); } break; } case CompilerDiagnosticIdentifiers.CS0750_PartialMethodCannotHaveAccessModifiersOrVirtualAbstractOverrideNewSealedOrExternModifiers: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier, context.Document, root.SyntaxTree)) { 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.CS1105_ExtensionMethodMustBeStatic: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddStaticModifier, context.Document, root.SyntaxTree)) { AddStaticModifier(context, diagnostic, node, CodeFixIdentifiers.AddStaticModifier); } if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveThisModifier, context.Document, root.SyntaxTree)) { 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.CS1106_ExtensionMethodMustBeDefinedInNonGenericStaticClass: { if (node is not ClassDeclarationSyntax classDeclaration) { return; } if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddStaticModifier, context.Document, root.SyntaxTree) && !classDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword)) { AddStaticModifier(context, diagnostic, node, CodeFixIdentifiers.AddStaticModifier); } if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveThisModifier, context.Document, root.SyntaxTree)) { 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.CS0759_NoDefiningDeclarationFoundForImplementingDeclarationOfPartialMethod: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.PartialKeyword); } break; } case CompilerDiagnosticIdentifiers.CS1100_MethodHasParameterModifierThisWhichIsNotOnFirstParameter: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveThisModifier, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, token.Parent, token); } break; } case CompilerDiagnosticIdentifiers.CS0708_CannotDeclareInstanceMembersInStaticClass: case CompilerDiagnosticIdentifiers.CS0710_StaticClassesCannotHaveInstanceConstructors: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddStaticModifier, context.Document, root.SyntaxTree)) { AddStaticModifier(context, diagnostic, node, CodeFixIdentifiers.AddStaticModifier); } if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeContainingClassNonStatic, context.Document, root.SyntaxTree)) { 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.CS1527_ElementsDefinedInNamespaceCannotBeExplicitlyDeclaredAsPrivateProtectedOrProtectedInternal: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeAccessibility, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.ChangeAccessibility(context, diagnostic, node, _publicOrInternal); } break; } case CompilerDiagnosticIdentifiers.CS0101_NamespaceAlreadyContainsDefinition: case CompilerDiagnosticIdentifiers.CS0102_TypeAlreadyContainsDefinition: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddPartialModifier, context.Document, root.SyntaxTree)) { break; } if (!node.IsKind( SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration, SyntaxKind.RecordStructDeclaration, 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.CS0115_NoSuitableMethodFoundToOverride: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveInvalidModifier, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.OverrideKeyword); } break; } case CompilerDiagnosticIdentifiers.CS1988_AsyncMethodsCannotHaveRefOrOutParameters: case CompilerDiagnosticIdentifiers.CS1623_IteratorsCannotHaveRefOrOutParameters: case CompilerDiagnosticIdentifiers.CS0192_ReadOnlyFieldCannotBePassedAsRefOrOutValue: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveRefModifier, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.RefKeyword, additionalKey: nameof(SyntaxKind.RefKeyword)); } if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveOutModifier, context.Document, root.SyntaxTree)) { ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.OutKeyword, additionalKey: nameof(SyntaxKind.OutKeyword)); } break; } case CompilerDiagnosticIdentifiers.CS0573_CannotHaveInstancePropertyOrFieldInitializersInStruct: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddStaticModifier, context.Document, root.SyntaxTree)) { AddStaticModifier(context, diagnostic, node); } break; } case CompilerDiagnosticIdentifiers.CS0501_MemberMustDeclareBodyBecauseItIsNotMarkedAbstractExternOrPartial: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddModifierAbstract, context.Document, root.SyntaxTree) && node.IsKind(SyntaxKind.MethodDeclaration) && (node.Parent as ClassDeclarationSyntax)?.Modifiers.Contains(SyntaxKind.AbstractKeyword) == true) { ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.AbstractKeyword); } break; } case CompilerDiagnosticIdentifiers.CS0549_NewVirtualMemberInSealedClass: { if (IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveVirtualModifier, context.Document, root.SyntaxTree)) { 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 (IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeContainingClassUnsealed, context.Document, root.SyntaxTree) && node.Parent is ClassDeclarationSyntax classDeclaration) { ModifiersCodeFixRegistrator.RemoveModifier( context, diagnostic, classDeclaration, SyntaxKind.SealedKeyword, title: "Make containing class unsealed", additionalKey: CodeFixIdentifiers.MakeContainingClassUnsealed); } break; } case CompilerDiagnosticIdentifiers.CS8340_InstanceFieldsOfReadOnlyStructsMustBeReadOnly: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeMemberReadOnly, context.Document, root.SyntaxTree)) { break; } ModifiersCodeFixRegistrator.AddModifier(context, diagnostic, node, SyntaxKind.ReadOnlyKeyword); break; } case CompilerDiagnosticIdentifiers.CS0238_MemberCannotBeSealedBecauseItIsNotOverride: { if (!IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveSealedModifier, context.Document, root.SyntaxTree)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (semanticModel.GetDiagnostic( CompilerDiagnosticIdentifiers.CS0114_MemberHidesInheritedMemberToMakeCurrentMethodOverrideThatImplementationAddOverrideKeyword, CSharpUtility.GetIdentifier(node).Span, context.CancellationToken) != null) { break; } ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, node, SyntaxKind.SealedKeyword); break; } } } }