public static async Task ComputeRefactoringsAsync(RefactoringContext context, SyntaxToken modifier) { SyntaxNode node = modifier.Parent; if (node.IsKind(SyntaxKind.DestructorDeclaration)) { return; } ModifiersInfo modifiersInfo = SyntaxInfo.ModifiersInfo(node); if (node.IsKind( SyntaxKind.ClassDeclaration, SyntaxKind.InterfaceDeclaration, SyntaxKind.StructDeclaration)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var symbol = (INamedTypeSymbol)semanticModel.GetDeclaredSymbol(node, context.CancellationToken); ImmutableArray <SyntaxReference> syntaxReferences = symbol.DeclaringSyntaxReferences; if (syntaxReferences.Length > 1) { ImmutableArray <MemberDeclarationSyntax> memberDeclarations = ImmutableArray.CreateRange( syntaxReferences, f => (MemberDeclarationSyntax)f.GetSyntax(context.CancellationToken)); foreach (Accessibility accessibility in ChangeAccessibilityRefactoring.Accessibilities) { if (accessibility != modifiersInfo.Accessibility && CSharpUtility.IsAllowedAccessibility(node, accessibility)) { context.RegisterRefactoring( ChangeAccessibilityRefactoring.GetTitle(accessibility), cancellationToken => ChangeAccessibilityRefactoring.RefactorAsync(context.Solution, memberDeclarations, accessibility, cancellationToken)); } } return; } } foreach (Accessibility accessibility in ChangeAccessibilityRefactoring.Accessibilities) { if (accessibility == modifiersInfo.Accessibility) { continue; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol symbol = GetBaseSymbolOrDefault(semanticModel, context.CancellationToken); if (symbol != null) { if (CSharpUtility.IsAllowedAccessibility(node, accessibility, allowOverride: true)) { context.RegisterRefactoring( ChangeAccessibilityRefactoring.GetTitle(accessibility), cancellationToken => ChangeAccessibilityRefactoring.RefactorAsync(context.Solution, symbol, accessibility, cancellationToken)); } } else if (CSharpUtility.IsAllowedAccessibility(node, accessibility)) { context.RegisterRefactoring( ChangeAccessibilityRefactoring.GetTitle(accessibility), cancellationToken => ChangeAccessibilityRefactoring.RefactorAsync(context.Document, node, accessibility, cancellationToken)); } } ISymbol GetBaseSymbolOrDefault(SemanticModel semanticModel, CancellationToken cancellationToken) { if (modifiersInfo.HasAbstractOrVirtualOrOverride) { return(ChangeAccessibilityRefactoring.GetBaseSymbolOrDefault(node, semanticModel, cancellationToken)); } return(null); } }
public static bool IsAllowedAccessibility(SyntaxNode node, Accessibility accessibility, bool allowOverride = false) { 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; ModifiersInfo info = SyntaxInfo.ModifiersInfo(eventDeclaration); return((allowOverride || !info.HasOverride) && (!accessibility.IsPrivate() || !info.HasAbstractOrVirtualOrOverride) && CheckProtectedInStaticOrSealedClass(node, accessibility) && CheckAccessorAccessibility(eventDeclaration.AccessorList, accessibility)); } case SyntaxKind.IndexerDeclaration: { var indexerDeclaration = (IndexerDeclarationSyntax)node; ModifiersInfo info = SyntaxInfo.ModifiersInfo(indexerDeclaration); return((allowOverride || !info.HasOverride) && (!accessibility.IsPrivate() || !info.HasAbstractOrVirtualOrOverride) && CheckProtectedInStaticOrSealedClass(node, accessibility) && CheckAccessorAccessibility(indexerDeclaration.AccessorList, accessibility)); } case SyntaxKind.PropertyDeclaration: { var propertyDeclaration = (PropertyDeclarationSyntax)node; ModifiersInfo info = SyntaxInfo.ModifiersInfo(propertyDeclaration); return((allowOverride || !info.HasOverride) && (!accessibility.IsPrivate() || !info.HasAbstractOrVirtualOrOverride) && CheckProtectedInStaticOrSealedClass(node, accessibility) && CheckAccessorAccessibility(propertyDeclaration.AccessorList, accessibility)); } case SyntaxKind.MethodDeclaration: { var methodDeclaration = (MethodDeclarationSyntax)node; ModifiersInfo info = SyntaxInfo.ModifiersInfo(methodDeclaration); return((allowOverride || !info.HasOverride) && (!accessibility.IsPrivate() || !info.HasAbstractOrVirtualOrOverride) && CheckProtectedInStaticOrSealedClass(node, accessibility)); } case SyntaxKind.EventFieldDeclaration: { var eventFieldDeclaration = (EventFieldDeclarationSyntax)node; ModifiersInfo info = SyntaxInfo.ModifiersInfo(eventFieldDeclaration); return((allowOverride || !info.HasOverride) && (!accessibility.IsPrivate() || !info.HasAbstractOrVirtualOrOverride) && CheckProtectedInStaticOrSealedClass(node, accessibility)); } case SyntaxKind.ConstructorDeclaration: case SyntaxKind.DelegateDeclaration: case SyntaxKind.FieldDeclaration: case SyntaxKind.IncompleteMember: { return(CheckProtectedInStaticOrSealedClass(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 (!CheckProtectedInStaticOrSealedClass(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); } } }