public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeAccessibility)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf( root, context.Span, out SyntaxNode node, predicate: f => OverrideInfo.CanCreate(f))) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.CannotChangeAccessModifiersWhenOverridingInheritedMember: { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); OverrideInfo overrideInfo = OverrideInfo.Create(node, semanticModel, context.CancellationToken); if (!overrideInfo.Success) { break; } Accessibility newAccessibility = overrideInfo.OverriddenSymbol.DeclaredAccessibility; CodeAction codeAction = CodeAction.Create( $"Change accessibility to '{AccessibilityHelper.GetAccessibilityName(newAccessibility)}'", cancellationToken => { if (node.Kind() == SyntaxKind.VariableDeclarator) { node = node.Parent.Parent; } SyntaxNode newNode = AccessibilityHelper.ChangeAccessibility(node, newAccessibility, ModifierComparer.Instance); return(context.Document.ReplaceNodeAsync(node, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }
private void ChangeAccessibility(CodeFixContext context, Diagnostic diagnostic, SyntaxNode node, Accessibility[] accessibilities) { foreach (Accessibility accessibility in accessibilities) { if (AccessibilityHelper.IsAllowedAccessibility(node, accessibility)) { CodeAction codeAction = CodeAction.Create( $"Change accessibility to '{AccessibilityHelper.GetAccessibilityName(accessibility)}'", cancellationToken => ChangeAccessibilityRefactoring.RefactorAsync(context.Document, node, accessibility, cancellationToken), GetEquivalenceKey(diagnostic.Id, accessibility.ToString())); context.RegisterCodeFix(codeAction, diagnostic); } } }
public static void ChangeAccessibility( CodeFixContext context, Diagnostic diagnostic, SyntaxNode node, Accessibility accessibility) { if (!CSharpUtility.IsAllowedAccessibility(node, accessibility)) { return; } CodeAction codeAction = CodeAction.Create( $"Change accessibility to '{AccessibilityHelper.GetAccessibilityName(accessibility)}'", cancellationToken => ChangeAccessibilityRefactoring.RefactorAsync(context.Document, node, accessibility, cancellationToken), GetEquivalenceKey(diagnostic, accessibility.ToString())); context.RegisterCodeFix(codeAction, diagnostic); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.SynchronizeAccessibility)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); MemberDeclarationSyntax memberDeclaration = root .FindNode(context.Span, getInnermostNodeForTie: true)? .FirstAncestorOrSelf <MemberDeclarationSyntax>(); Debug.Assert(memberDeclaration != null, $"{nameof(memberDeclaration)} is null"); if (memberDeclaration == null) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var symbol = (INamedTypeSymbol)semanticModel.GetDeclaredSymbol(memberDeclaration, context.CancellationToken); ImmutableArray <MemberDeclarationSyntax> memberDeclarations = ImmutableArray.CreateRange( symbol.DeclaringSyntaxReferences, f => (MemberDeclarationSyntax)f.GetSyntax(context.CancellationToken)); foreach (Accessibility accessibility in memberDeclarations .Select(f => f.GetModifiers().GetAccessibility()) .Where(f => f != Accessibility.NotApplicable)) { if (AccessibilityHelper.IsAllowedAccessibility(memberDeclaration, accessibility)) { CodeAction codeAction = CodeAction.Create( $"Change accessibility to '{AccessibilityHelper.GetAccessibilityName(accessibility)}'", cancellationToken => ChangeAccessibilityRefactoring.RefactorAsync(context.Solution(), memberDeclarations, accessibility, cancellationToken), GetEquivalenceKey(CompilerDiagnosticIdentifiers.PartialDeclarationsHaveConfictingAccessibilityModifiers, accessibility.ToString())); context.RegisterCodeFix(codeAction, context.Diagnostics); } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.OverridingMemberCannotChangeAccessModifiers) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddDocumentationComment) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMethodReturnType) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MemberTypeMustMatchOverriddenMemberType) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddPartialModifier) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeMemberNonStatic) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveParametersFromStaticConstructor)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); MemberDeclarationSyntax memberDeclaration = root .FindNode(context.Span, getInnermostNodeForTie: true)? .FirstAncestorOrSelf <MemberDeclarationSyntax>(); Debug.Assert(memberDeclaration != null, $"{nameof(memberDeclaration)} is null"); if (memberDeclaration == null) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.CannotChangeAccessModifiersWhenOverridingInheritedMember: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.OverridingMemberCannotChangeAccessModifiers)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); OverrideInfo overrideInfo = OverridingMemberCannotChangeAccessModifiersRefactoring.GetOverrideInfo(memberDeclaration, semanticModel, context.CancellationToken); Accessibility newAccessibility = overrideInfo.OverriddenSymbol.DeclaredAccessibility; string title = $"Change accessibility to '{AccessibilityHelper.GetAccessibilityName(newAccessibility)}'"; CodeAction codeAction = CodeAction.Create( title, cancellationToken => OverridingMemberCannotChangeAccessModifiersRefactoring.RefactorAsync(context.Document, memberDeclaration, newAccessibility, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } 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) { TypeSyntax newType = typeSymbol.ToMinimalTypeSyntax(semanticModel, memberDeclaration.SpanStart); 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; } CodeAction codeAction = CodeAction.Create( "Add 'partial' modifier", cancellationToken => { if (memberDeclaration.IsKind(SyntaxKind.MethodDeclaration) && memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration)) { return(context.Document.InsertModifierAsync(memberDeclaration.Parent, SyntaxKind.PartialKeyword, ModifierComparer.Instance, cancellationToken)); } else if (memberDeclaration.IsKind(SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration, SyntaxKind.InterfaceDeclaration)) { return(context.Document.InsertModifierAsync(memberDeclaration, SyntaxKind.PartialKeyword, ModifierComparer.Instance, cancellationToken)); } return(Task.FromResult(context.Document)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.MemberIsAbstractButItIsContainedInNonAbstractClass: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeContainingClassAbstract)) { break; } if (!memberDeclaration.IsParentKind(SyntaxKind.ClassDeclaration)) { break; } CodeAction codeAction = CodeAction.Create( "Make containing class abstract", cancellationToken => context.Document.InsertModifierAsync(memberDeclaration.Parent, SyntaxKind.AbstractKeyword, ModifierComparer.Instance, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.ObjectReferenceIsRequiredForNonStaticMember: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.MakeMemberNonStatic)) { break; } SyntaxTokenList modifiers = memberDeclaration.GetModifiers(); Debug.Assert(modifiers.Contains(SyntaxKind.StaticKeyword), memberDeclaration.ToString()); if (!modifiers.Contains(SyntaxKind.StaticKeyword)) { break; } CodeAction codeAction = CodeAction.Create( $"Make containing {memberDeclaration.GetTitle()} non-static", cancellationToken => context.Document.RemoveModifierAsync(memberDeclaration, SyntaxKind.StaticKeyword, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); 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; } } } }
private static string GetTitle(Accessibility accessibility) { return($"Change accessibility to '{AccessibilityHelper.GetAccessibilityName(accessibility)}'"); }