public static async Task <Solution> RefactorAsync( Solution solution, MemberDeclarationListSelection selectedMembers, Accessibility newAccessibility, SemanticModel semanticModel, CancellationToken cancellationToken) { var members = new HashSet <MemberDeclarationSyntax>(); foreach (MemberDeclarationSyntax member in selectedMembers) { ModifierFilter filter = SyntaxInfo.ModifierListInfo(member).GetFilter(); if (filter.Any(ModifierFilter.Partial)) { ISymbol symbol = semanticModel.GetDeclaredSymbol(member, cancellationToken); foreach (SyntaxReference reference in symbol.DeclaringSyntaxReferences) { members.Add((MemberDeclarationSyntax)reference.GetSyntax(cancellationToken)); } } else if (filter.Any(ModifierFilter.AbstractVirtualOverride)) { ISymbol symbol = GetBaseSymbolOrDefault(member, semanticModel, cancellationToken); if (symbol != null) { foreach (MemberDeclarationSyntax member2 in GetMemberDeclarations(symbol, cancellationToken)) { members.Add(member2); } foreach (MemberDeclarationSyntax member2 in await FindOverridingMemberDeclarationsAsync(symbol, solution, cancellationToken).ConfigureAwait(false)) { members.Add(member2); } } else { members.Add(member); } } else { members.Add(member); } } return(await solution.ReplaceNodesAsync( members, (node, _) => SyntaxAccessibility.WithExplicitAccessibility(node, newAccessibility), cancellationToken) .ConfigureAwait(false)); }
/// <summary> /// Returns true if the node can have specified accessibility. /// </summary> /// <param name="node"></param> /// <param name="accessibility"></param> /// <param name="ignoreOverride">Ignore "override" modifier.</param> /// <returns></returns> public static bool IsValidAccessibility(SyntaxNode node, Accessibility accessibility, bool ignoreOverride = false) { if (node == null) { throw new ArgumentNullException(nameof(node)); } switch (node.Parent?.Kind()) { case SyntaxKind.NamespaceDeclaration: case SyntaxKind.CompilationUnit: { return(accessibility.Is(Accessibility.Public, Accessibility.Internal)); } case SyntaxKind.StructDeclaration: { if (accessibility.ContainsProtected()) { return(false); } break; } } switch (node.Kind()) { case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.EnumDeclaration: { return(true); } case SyntaxKind.EventDeclaration: { var eventDeclaration = (EventDeclarationSyntax)node; ModifierFilter filter = SyntaxInfo.ModifierListInfo(eventDeclaration).GetFilter(); return((ignoreOverride || !filter.Any(ModifierFilter.Override)) && (accessibility != Accessibility.Private || !filter.Any(ModifierFilter.AbstractVirtualOverride)) && CheckProtectedInStaticOrSealedClass(node) && CheckAccessorAccessibility(eventDeclaration.AccessorList)); } case SyntaxKind.IndexerDeclaration: { var indexerDeclaration = (IndexerDeclarationSyntax)node; ModifierFilter filter = SyntaxInfo.ModifierListInfo(indexerDeclaration).GetFilter(); return((ignoreOverride || !filter.Any(ModifierFilter.Override)) && (accessibility != Accessibility.Private || !filter.Any(ModifierFilter.AbstractVirtualOverride)) && CheckProtectedInStaticOrSealedClass(node) && CheckAccessorAccessibility(indexerDeclaration.AccessorList)); } case SyntaxKind.PropertyDeclaration: { var propertyDeclaration = (PropertyDeclarationSyntax)node; ModifierFilter filter = SyntaxInfo.ModifierListInfo(propertyDeclaration).GetFilter(); return((ignoreOverride || !filter.Any(ModifierFilter.Override)) && (accessibility != Accessibility.Private || !filter.Any(ModifierFilter.AbstractVirtualOverride)) && CheckProtectedInStaticOrSealedClass(node) && CheckAccessorAccessibility(propertyDeclaration.AccessorList)); } case SyntaxKind.MethodDeclaration: { var methodDeclaration = (MethodDeclarationSyntax)node; ModifierFilter filter = SyntaxInfo.ModifierListInfo(methodDeclaration).GetFilter(); return((ignoreOverride || !filter.Any(ModifierFilter.Override)) && (accessibility != Accessibility.Private || !filter.Any(ModifierFilter.AbstractVirtualOverride)) && CheckProtectedInStaticOrSealedClass(node)); } case SyntaxKind.EventFieldDeclaration: { var eventFieldDeclaration = (EventFieldDeclarationSyntax)node; ModifierFilter filter = SyntaxInfo.ModifierListInfo(eventFieldDeclaration).GetFilter(); return((ignoreOverride || !filter.Any(ModifierFilter.Override)) && (accessibility != Accessibility.Private || !filter.Any(ModifierFilter.AbstractVirtualOverride)) && CheckProtectedInStaticOrSealedClass(node)); } case SyntaxKind.ConstructorDeclaration: case SyntaxKind.DelegateDeclaration: case SyntaxKind.FieldDeclaration: case SyntaxKind.IncompleteMember: { return(CheckProtectedInStaticOrSealedClass(node)); } case SyntaxKind.OperatorDeclaration: case SyntaxKind.ConversionOperatorDeclaration: { return(accessibility == Accessibility.Public); } case SyntaxKind.GetAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: case SyntaxKind.AddAccessorDeclaration: case SyntaxKind.RemoveAccessorDeclaration: case SyntaxKind.UnknownAccessorDeclaration: { var memberDeclaration = node.Parent?.Parent as MemberDeclarationSyntax; Debug.Assert(memberDeclaration != null, node.ToString()); if (memberDeclaration != null) { if (!CheckProtectedInStaticOrSealedClass(memberDeclaration)) { return(false); } return(accessibility.IsMoreRestrictiveThan(GetAccessibility(memberDeclaration))); } return(false); } case SyntaxKind.LocalFunctionStatement: { return(false); } default: { Debug.Fail(node.Kind().ToString()); return(false); } } bool CheckProtectedInStaticOrSealedClass(SyntaxNode declaration) { return(!accessibility.ContainsProtected() || (declaration.Parent as ClassDeclarationSyntax)? .Modifiers .ContainsAny(SyntaxKind.StaticKeyword, SyntaxKind.SealedKeyword) != true); } bool CheckAccessorAccessibility(AccessorListSyntax accessorList) { if (accessorList != null) { foreach (AccessorDeclarationSyntax accessor in accessorList.Accessors) { Accessibility accessorAccessibility = GetExplicitAccessibility(accessor.Modifiers); if (accessorAccessibility != Accessibility.NotApplicable) { return(accessorAccessibility.IsMoreRestrictiveThan(accessibility)); } } } return(true); } }