private static bool CheckProtectedOrProtectedInternalInStaticOrSealedClass(SyntaxNode node, Accessibility accessibility) { return(!accessibility.ContainsProtected() || (node.Parent as ClassDeclarationSyntax)? .Modifiers .ContainsAny(SyntaxKind.StaticKeyword, SyntaxKind.SealedKeyword) != true); }
public static bool IsAllowedAccessibility(SyntaxNode node, Accessibility accessibility) { 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; SyntaxTokenList modifiers = eventDeclaration.Modifiers; return(!modifiers.Contains(SyntaxKind.OverrideKeyword) && CheckPrivateForAbstractOrVirtualMember(accessibility, modifiers) && CheckProtectedOrProtectedInternalInStaticOrSealedClass(node, accessibility) && CheckAccessorAccessibility(eventDeclaration.AccessorList, accessibility)); } case SyntaxKind.IndexerDeclaration: { var indexerDeclaration = (IndexerDeclarationSyntax)node; SyntaxTokenList modifiers = indexerDeclaration.Modifiers; return(!modifiers.Contains(SyntaxKind.OverrideKeyword) && CheckPrivateForAbstractOrVirtualMember(accessibility, modifiers) && CheckProtectedOrProtectedInternalInStaticOrSealedClass(node, accessibility) && CheckAccessorAccessibility(indexerDeclaration.AccessorList, accessibility)); } case SyntaxKind.PropertyDeclaration: { var propertyDeclaration = (PropertyDeclarationSyntax)node; SyntaxTokenList modifiers = propertyDeclaration.Modifiers; return(!modifiers.Contains(SyntaxKind.OverrideKeyword) && CheckPrivateForAbstractOrVirtualMember(accessibility, modifiers) && CheckProtectedOrProtectedInternalInStaticOrSealedClass(node, accessibility) && CheckAccessorAccessibility(propertyDeclaration.AccessorList, accessibility)); } case SyntaxKind.MethodDeclaration: { var methodDeclaration = (MethodDeclarationSyntax)node; SyntaxTokenList modifiers = methodDeclaration.Modifiers; return(!modifiers.Contains(SyntaxKind.OverrideKeyword) && CheckPrivateForAbstractOrVirtualMember(accessibility, modifiers) && CheckProtectedOrProtectedInternalInStaticOrSealedClass(node, accessibility)); } case SyntaxKind.EventFieldDeclaration: { var eventFieldDeclaration = (EventFieldDeclarationSyntax)node; SyntaxTokenList modifiers = eventFieldDeclaration.Modifiers; return(!modifiers.Contains(SyntaxKind.OverrideKeyword) && CheckPrivateForAbstractOrVirtualMember(accessibility, modifiers) && CheckProtectedOrProtectedInternalInStaticOrSealedClass(node, accessibility)); } case SyntaxKind.ConstructorDeclaration: case SyntaxKind.DelegateDeclaration: case SyntaxKind.FieldDeclaration: case SyntaxKind.IncompleteMember: { return(CheckProtectedOrProtectedInternalInStaticOrSealedClass(node, accessibility)); } 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 (!CheckProtectedOrProtectedInternalInStaticOrSealedClass(memberDeclaration, accessibility)) { return(false); } Accessibility declarationAccessibility = memberDeclaration.GetModifiers().GetAccessibility(); if (declarationAccessibility == Accessibility.NotApplicable) { declarationAccessibility = memberDeclaration.GetDefaultExplicitAccessibility(); } return(accessibility.IsMoreRestrictiveThan(declarationAccessibility)); } return(false); } case SyntaxKind.LocalFunctionStatement: { return(false); } default: { Debug.Fail(node.Kind().ToString()); return(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> 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: case SyntaxKind.RecordStructDeclaration: { if (accessibility.ContainsProtected()) { return(false); } break; } } switch (node.Kind()) { case SyntaxKind.ClassDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.RecordDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.RecordStructDeclaration: case SyntaxKind.EnumDeclaration: { return(true); } case SyntaxKind.EventDeclaration: { var eventDeclaration = (EventDeclarationSyntax)node; ModifierFilter filter = SyntaxInfo.ModifierListInfo(eventDeclaration).GetFilter(); return((ignoreOverride || !filter.HasAnyFlag(ModifierFilter.Override)) && (accessibility != Accessibility.Private || !filter.HasAnyFlag(ModifierFilter.AbstractVirtualOverride)) && CheckProtectedInStaticOrSealedClass(node) && CheckAccessorAccessibility(eventDeclaration.AccessorList)); } case SyntaxKind.IndexerDeclaration: { var indexerDeclaration = (IndexerDeclarationSyntax)node; ModifierFilter filter = SyntaxInfo.ModifierListInfo(indexerDeclaration).GetFilter(); return((ignoreOverride || !filter.HasAnyFlag(ModifierFilter.Override)) && (accessibility != Accessibility.Private || !filter.HasAnyFlag(ModifierFilter.AbstractVirtualOverride)) && CheckProtectedInStaticOrSealedClass(node) && CheckAccessorAccessibility(indexerDeclaration.AccessorList)); } case SyntaxKind.PropertyDeclaration: { var propertyDeclaration = (PropertyDeclarationSyntax)node; ModifierFilter filter = SyntaxInfo.ModifierListInfo(propertyDeclaration).GetFilter(); return((ignoreOverride || !filter.HasAnyFlag(ModifierFilter.Override)) && (accessibility != Accessibility.Private || !filter.HasAnyFlag(ModifierFilter.AbstractVirtualOverride)) && CheckProtectedInStaticOrSealedClass(node) && CheckAccessorAccessibility(propertyDeclaration.AccessorList)); } case SyntaxKind.MethodDeclaration: { var methodDeclaration = (MethodDeclarationSyntax)node; ModifierFilter filter = SyntaxInfo.ModifierListInfo(methodDeclaration).GetFilter(); return((ignoreOverride || !filter.HasAnyFlag(ModifierFilter.Override)) && (accessibility != Accessibility.Private || !filter.HasAnyFlag(ModifierFilter.AbstractVirtualOverride)) && CheckProtectedInStaticOrSealedClass(node)); } case SyntaxKind.EventFieldDeclaration: { var eventFieldDeclaration = (EventFieldDeclarationSyntax)node; ModifierFilter filter = SyntaxInfo.ModifierListInfo(eventFieldDeclaration).GetFilter(); return((ignoreOverride || !filter.HasAnyFlag(ModifierFilter.Override)) && (accessibility != Accessibility.Private || !filter.HasAnyFlag(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.InitAccessorDeclaration: case SyntaxKind.UnknownAccessorDeclaration: { var memberDeclaration = node.Parent?.Parent as MemberDeclarationSyntax; SyntaxDebug.Assert(memberDeclaration != null, node); if (memberDeclaration != null) { if (!CheckProtectedInStaticOrSealedClass(memberDeclaration)) { return(false); } return(accessibility.IsMoreRestrictiveThan(GetAccessibility(memberDeclaration))); } return(false); } case SyntaxKind.LocalFunctionStatement: { return(false); } default: { SyntaxDebug.Fail(node); 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); } }