private static Accessibility GetAccessibility(SyntaxNodeAnalysisContext context, MemberDeclarationSyntax declaration, SyntaxTokenList modifiers) { if (!modifiers.Any(f => SyntaxFacts.IsAccessibilityModifier(f.Kind()))) { if (modifiers.Any(SyntaxKind.PartialKeyword)) { if (!declaration.IsKind(SyntaxKind.MethodDeclaration)) { Accessibility?accessibility = GetPartialAccessModifier(context, declaration); if (accessibility != null) { if (accessibility == Accessibility.NotApplicable) { return(SyntaxAccessibility.GetDefaultExplicitAccessibility(declaration)); } else { return(accessibility.Value); } } } } else { return(SyntaxAccessibility.GetDefaultExplicitAccessibility(declaration)); } } return(Accessibility.NotApplicable); }
private static TNode AddModifier<TNode>( TNode node, SyntaxKind modifierKind, IComparer<SyntaxKind> comparer = null) where TNode : SyntaxNode { switch (modifierKind) { case SyntaxKind.AbstractKeyword: { node = node.RemoveModifiers(SyntaxKind.VirtualKeyword, SyntaxKind.OverrideKeyword); break; } case SyntaxKind.VirtualKeyword: { node = node.RemoveModifiers(SyntaxKind.AbstractKeyword, SyntaxKind.OverrideKeyword); break; } case SyntaxKind.OverrideKeyword: { node = node.RemoveModifiers(SyntaxKind.AbstractKeyword, SyntaxKind.VirtualKeyword); break; } case SyntaxKind.StaticKeyword: { if (node.IsKind(SyntaxKind.ConstructorDeclaration)) node = SyntaxAccessibility.WithoutExplicitAccessibility(node); node = node.RemoveModifier(SyntaxKind.SealedKeyword); break; } } return node.InsertModifier(modifierKind, comparer); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { Diagnostic diagnostic = context.Diagnostics[0]; if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MarkOperatorAsPublicAndStatic)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration)) { return; } ModifierListInfo info = SyntaxInfo.ModifierListInfo(memberDeclaration); var title = "Add "; if (info.ExplicitAccessibility == Accessibility.Public) { title += "modifier 'static'"; } else if (info.IsStatic) { title += "modifier 'public'"; } else { title += "modifiers 'public static'"; } CodeAction codeAction = CodeAction.Create( title, cancellationToken => { SyntaxNode newNode = memberDeclaration; if (info.Modifiers.ContainsAny(SyntaxKind.InternalKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.PrivateKeyword)) { newNode = SyntaxAccessibility.WithoutExplicitAccessibility(newNode); } if (!info.Modifiers.Contains(SyntaxKind.PublicKeyword)) { newNode = ModifierList.Insert(newNode, SyntaxKind.PublicKeyword); } if (!info.IsStatic) { newNode = ModifierList.Insert(newNode, SyntaxKind.StaticKeyword); } return(context.Document.ReplaceNodeAsync(memberDeclaration, newNode, cancellationToken)); }, base.GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); }
private static Accessibility?GetPartialAccessModifier( SyntaxNodeAnalysisContext context, MemberDeclarationSyntax declaration) { var accessibility = Accessibility.NotApplicable; ISymbol symbol = context.SemanticModel.GetDeclaredSymbol(declaration, context.CancellationToken); if (symbol != null) { foreach (SyntaxReference syntaxReference in symbol.DeclaringSyntaxReferences) { if (syntaxReference.GetSyntax(context.CancellationToken) is MemberDeclarationSyntax declaration2) { Accessibility accessibility2 = SyntaxAccessibility.GetExplicitAccessibility(declaration2); if (accessibility2 != Accessibility.NotApplicable) { if (accessibility == Accessibility.NotApplicable || accessibility == accessibility2) { accessibility = accessibility2; } else { return(null); } } } } } return(accessibility); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { Diagnostic diagnostic = context.Diagnostics[0]; if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeAccessibility)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf( root, context.Span, out SyntaxNode node, predicate: CSharpOverriddenSymbolInfo.CanCreate)) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); OverriddenSymbolInfo overrideInfo = CSharpOverriddenSymbolInfo.Create(node, semanticModel, context.CancellationToken); if (!overrideInfo.Success) { return; } Accessibility newAccessibility = overrideInfo.OverriddenSymbol.DeclaredAccessibility; CodeAction codeAction = CodeAction.Create( $"Change accessibility to '{SyntaxFacts.GetText(newAccessibility)}'", cancellationToken => { if (node.Kind() == SyntaxKind.VariableDeclarator) { node = node.Parent.Parent; } SyntaxNode newNode; if (newAccessibility == Accessibility.Public && node is AccessorDeclarationSyntax) { newNode = SyntaxAccessibility.WithoutExplicitAccessibility(node); } else { newNode = SyntaxAccessibility.WithExplicitAccessibility(node, newAccessibility); } return(context.Document.ReplaceNodeAsync(node, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); }
public static Task <Document> RefactorAsync( Document document, ConstructorDeclarationSyntax constructorDeclaration, CancellationToken cancellationToken) { ConstructorDeclarationSyntax newNode = SyntaxAccessibility.WithExplicitAccessibility(constructorDeclaration, Accessibility.Protected); return(document.ReplaceNodeAsync(constructorDeclaration, newNode, cancellationToken)); }
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 => OverriddenSymbolInfo.CanCreate(f))) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.CannotChangeAccessModifiersWhenOverridingInheritedMember: { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); OverriddenSymbolInfo overrideInfo = OverriddenSymbolInfo.Create(node, semanticModel, context.CancellationToken); if (!overrideInfo.Success) { break; } Accessibility newAccessibility = overrideInfo.OverriddenSymbol.DeclaredAccessibility; CodeAction codeAction = CodeAction.Create( $"Change accessibility to '{SyntaxFacts.GetText(newAccessibility)}'", cancellationToken => { if (node.Kind() == SyntaxKind.VariableDeclarator) { node = node.Parent.Parent; } SyntaxNode newNode = SyntaxAccessibility.WithExplicitAccessibility(node, newAccessibility); return(context.Document.ReplaceNodeAsync(node, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }
public static Task <Document> RefactorAsync( Document document, SyntaxNode node, Accessibility newAccessibility, CancellationToken cancellationToken) { SyntaxNode newNode = SyntaxAccessibility.WithExplicitAccessibility(node, newAccessibility); return(document.ReplaceNodeAsync(node, newNode, cancellationToken)); }
public static Task <Document> RefactorAsync( Document document, MemberDeclarationSyntax memberDeclaration, Accessibility accessibility, CancellationToken cancellationToken) { MemberDeclarationSyntax newNode = SyntaxAccessibility.WithExplicitAccessibility(memberDeclaration, accessibility); return(document.ReplaceNodeAsync(memberDeclaration, newNode, cancellationToken)); }
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.HasAnyFlag(ModifierFilter.Partial)) { ISymbol symbol = semanticModel.GetDeclaredSymbol(member, cancellationToken); foreach (SyntaxReference reference in symbol.DeclaringSyntaxReferences) { members.Add((MemberDeclarationSyntax)reference.GetSyntax(cancellationToken)); } } else if (filter.HasAnyFlag(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)); }
public static Task <Document> RefactorAsync( Document document, PropertyDeclarationSyntax propertyDeclaration, CancellationToken cancellationToken = default(CancellationToken)) { AccessorListSyntax accessorList = AccessorList(); if (propertyDeclaration.ExpressionBody != null) { accessorList = accessorList .AddAccessors(AutoGetAccessorDeclaration()); } else { AccessorDeclarationSyntax getter = propertyDeclaration.Getter(); if (getter != null) { if (SyntaxAccessibility.GetExplicitAccessibility(getter) == Accessibility.Private) { getter = SyntaxAccessibility.WithExplicitAccessibility(getter, Accessibility.Protected); } accessorList = accessorList.AddAccessors(getter .WithBody(null) .WithSemicolonToken(SemicolonToken())); } AccessorDeclarationSyntax setter = propertyDeclaration.Setter(); if (setter != null) { if (SyntaxAccessibility.GetExplicitAccessibility(setter) == Accessibility.Private) { setter = SyntaxAccessibility.WithExplicitAccessibility(setter, Accessibility.Protected); } accessorList = accessorList.AddAccessors(setter .WithBody(null) .WithSemicolonToken(SemicolonToken())); } } PropertyDeclarationSyntax newNode = propertyDeclaration .WithExpressionBody(null) .WithSemicolonToken(default(SyntaxToken)) .WithAccessorList(accessorList) .InsertModifier(SyntaxKind.AbstractKeyword) .RemoveModifier(SyntaxKind.VirtualKeyword) .WithTriviaFrom(propertyDeclaration) .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(propertyDeclaration, newNode, cancellationToken)); }
public static void ChangeAccessibility( CodeFixContext context, Diagnostic diagnostic, SyntaxNode node, Accessibility accessibility) { if (!SyntaxAccessibility.IsValidAccessibility(node, accessibility)) return; CodeAction codeAction = CodeAction.Create( $"Change accessibility to '{GetText(accessibility)}'", ct => ChangeAccessibilityRefactoring.RefactorAsync(context.Document, node, accessibility, ct), GetEquivalenceKey(diagnostic, accessibility.ToString())); context.RegisterCodeFix(codeAction, diagnostic); }
public static void RemoveAccessibility( CodeFixContext context, Diagnostic diagnostic, SyntaxNode node, string additionalKey = null) { var accessModifier = default(SyntaxToken); foreach (SyntaxToken modifier in SyntaxInfo.ModifierListInfo(node).Modifiers) { if (IsAccessibilityModifier(modifier.Kind())) { if (IsAccessibilityModifier(accessModifier.Kind())) { accessModifier = default; break; } else { accessModifier = modifier; } } } if (IsAccessibilityModifier(accessModifier.Kind())) { RemoveModifier(context, diagnostic, node, accessModifier, additionalKey: additionalKey); } else { CodeAction codeAction = CodeAction.Create( "Remove access modifiers", cancellationToken => { SyntaxNode newNode = SyntaxAccessibility.WithoutExplicitAccessibility(node); return(context.Document.ReplaceNodeAsync(node, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic, additionalKey)); context.RegisterCodeFix(codeAction, diagnostic); } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { Diagnostic diagnostic = context.Diagnostics[0]; if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.SynchronizeAccessibility)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out MemberDeclarationSyntax memberDeclaration)) { 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 => SyntaxAccessibility.GetExplicitAccessibility(f)) .Where(f => f != Accessibility.NotApplicable)) { if (SyntaxAccessibility.IsValidAccessibility(memberDeclaration, accessibility)) { CodeAction codeAction = CodeAction.Create( $"Change accessibility to '{SyntaxFacts.GetText(accessibility)}'", cancellationToken => ChangeAccessibilityRefactoring.RefactorAsync(context.Solution(), memberDeclarations, accessibility, cancellationToken), GetEquivalenceKey(CompilerDiagnosticIdentifiers.PartialDeclarationsHaveConfictingAccessibilityModifiers, accessibility.ToString())); context.RegisterCodeFix(codeAction, diagnostic); } } }
public static void AnalyzeConstructorDeclaration(SyntaxNodeAnalysisContext context) { var constructorDeclaration = (ConstructorDeclarationSyntax)context.Node; if (!SyntaxAccessibility.GetExplicitAccessibility(constructorDeclaration).Is(Accessibility.Public, Accessibility.ProtectedOrInternal)) { return; } if (!constructorDeclaration.IsParentKind(SyntaxKind.ClassDeclaration)) { return; } var classDeclaration = (ClassDeclarationSyntax)constructorDeclaration.Parent; SyntaxTokenList modifiers = classDeclaration.Modifiers; bool isAbstract = modifiers.Contains(SyntaxKind.AbstractKeyword); if (!isAbstract && modifiers.Contains(SyntaxKind.PartialKeyword)) { INamedTypeSymbol classSymbol = context.SemanticModel.GetDeclaredSymbol(classDeclaration, context.CancellationToken); if (classSymbol != null) { isAbstract = classSymbol.IsAbstract; } } if (!isAbstract) { return; } context.ReportDiagnostic(DiagnosticDescriptors.AbstractTypeShouldNotHavePublicConstructors, constructorDeclaration.Identifier); }
public static Accessibilities GetValidAccessibilities(MemberDeclarationListSelection selectedMembers, bool allowOverride = false) { if (selectedMembers.Count < 2) { return(Accessibilities.None); } var all = Accessibilities.None; Accessibilities valid = Accessibilities.Public | Accessibilities.Internal | Accessibilities.Protected | Accessibilities.Private; foreach (MemberDeclarationSyntax member in selectedMembers) { Accessibility accessibility = SyntaxAccessibility.GetExplicitAccessibility(member); if (accessibility == Accessibility.NotApplicable) { accessibility = SyntaxAccessibility.GetDefaultExplicitAccessibility(member); if (accessibility == Accessibility.NotApplicable) { return(Accessibilities.None); } } Accessibilities accessibilities = accessibility.GetAccessibilities(); switch (accessibility) { case Accessibility.Private: case Accessibility.Protected: case Accessibility.ProtectedAndInternal: case Accessibility.ProtectedOrInternal: case Accessibility.Internal: case Accessibility.Public: { all |= accessibilities; break; } default: { Debug.Fail(accessibility.ToString()); return(Accessibilities.None); } } foreach (Accessibility accessibility2 in AvailableAccessibilities) { if (accessibility != accessibility2 && !SyntaxAccessibility.IsValidAccessibility(member, accessibility2, ignoreOverride: allowOverride)) { valid &= ~accessibility2.GetAccessibilities(); } } } switch (all) { case Accessibilities.Private: case Accessibilities.Protected: case Accessibilities.Internal: case Accessibilities.Public: { valid &= ~all; break; } } return(valid); }
public static AccessibilityFilter GetValidAccessibilityFilter( MemberDeclarationListSelection selectedMembers, SemanticModel semanticModel, CancellationToken cancellationToken = default(CancellationToken)) { if (selectedMembers.Count < 2) { return(AccessibilityFilter.None); } ImmutableArray <Accessibility> avaiableAccessibilities = AvailableAccessibilities; var all = AccessibilityFilter.None; AccessibilityFilter valid = AccessibilityFilter.Public | AccessibilityFilter.Internal | AccessibilityFilter.Protected | AccessibilityFilter.Private; foreach (MemberDeclarationSyntax member in selectedMembers) { Accessibility accessibility = SyntaxAccessibility.GetExplicitAccessibility(member); if (accessibility == Accessibility.NotApplicable) { accessibility = SyntaxAccessibility.GetDefaultExplicitAccessibility(member); if (accessibility == Accessibility.NotApplicable) { return(AccessibilityFilter.None); } } switch (accessibility) { case Accessibility.Private: case Accessibility.Protected: case Accessibility.ProtectedAndInternal: case Accessibility.ProtectedOrInternal: case Accessibility.Internal: case Accessibility.Public: { all |= accessibility.GetAccessibilityFilter(); break; } default: { Debug.Fail(accessibility.ToString()); return(AccessibilityFilter.None); } } ModifierListInfo modifiersInfo = SyntaxInfo.ModifierListInfo(member); if (modifiersInfo.Modifiers.ContainsAny( SyntaxKind.AbstractKeyword, SyntaxKind.VirtualKeyword, SyntaxKind.OverrideKeyword)) { valid &= ~AccessibilityFilter.Private; } if (modifiersInfo.IsOverride && IsBaseDeclarationWithoutSource(member, semanticModel, cancellationToken)) { switch (accessibility) { case Accessibility.Private: case Accessibility.Protected: case Accessibility.Internal: case Accessibility.Public: { valid &= accessibility.GetAccessibilityFilter(); if (valid == AccessibilityFilter.None) { return(AccessibilityFilter.None); } avaiableAccessibilities = _accessibilityArrayMap[accessibility]; continue; } default: { return(AccessibilityFilter.None); } } } foreach (Accessibility accessibility2 in avaiableAccessibilities) { if (accessibility != accessibility2 && !SyntaxAccessibility.IsValidAccessibility(member, accessibility2, ignoreOverride: true)) { valid &= ~accessibility2.GetAccessibilityFilter(); if (valid == AccessibilityFilter.None) { return(AccessibilityFilter.None); } } } } switch (all) { case AccessibilityFilter.Private: case AccessibilityFilter.Protected: case AccessibilityFilter.Internal: case AccessibilityFilter.Public: { valid &= ~all; break; } } return(valid); }
private static void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context, TypeDeclarationSyntax typeDeclaration) { if (typeDeclaration.Modifiers.Contains(SyntaxKind.PartialKeyword)) { return; } SyntaxList <MemberDeclarationSyntax> members = typeDeclaration.Members; UnusedMemberWalker walker = null; foreach (MemberDeclarationSyntax member in members) { if (member.ContainsDiagnostics) { continue; } if (member.ContainsDirectives) { continue; } switch (member.Kind()) { case SyntaxKind.DelegateDeclaration: { var declaration = (DelegateDeclarationSyntax)member; if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(declaration.Identifier.ValueText, declaration); } break; } case SyntaxKind.EventDeclaration: { var declaration = (EventDeclarationSyntax)member; if (declaration.ExplicitInterfaceSpecifier == null && SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(declaration.Identifier.ValueText, declaration); } break; } case SyntaxKind.EventFieldDeclaration: { var declaration = (EventFieldDeclarationSyntax)member; if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNodes(declaration.Declaration); } break; } case SyntaxKind.FieldDeclaration: { var declaration = (FieldDeclarationSyntax)member; SyntaxTokenList modifiers = declaration.Modifiers; if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNodes(declaration.Declaration, isConst: modifiers.Contains(SyntaxKind.ConstKeyword)); } break; } case SyntaxKind.MethodDeclaration: { var declaration = (MethodDeclarationSyntax)member; SyntaxTokenList modifiers = declaration.Modifiers; if (declaration.ExplicitInterfaceSpecifier == null && !declaration.AttributeLists.Any() && SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { string methodName = declaration.Identifier.ValueText; if (!IsMainMethod(declaration, modifiers, methodName)) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(methodName, declaration); } } break; } case SyntaxKind.PropertyDeclaration: { var declaration = (PropertyDeclarationSyntax)member; if (declaration.ExplicitInterfaceSpecifier == null && SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(declaration.Identifier.ValueText, declaration); } break; } } } if (walker == null) { return; } walker.Visit(typeDeclaration); foreach (NodeSymbolInfo info in UnusedMemberWalkerCache.GetNodesAndFree(walker)) { SyntaxNode node = info.Node; if (node is VariableDeclaratorSyntax variableDeclarator) { var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent; if (variableDeclaration.Variables.Count == 1) { ReportDiagnostic(context, variableDeclaration.Parent, CSharpFacts.GetTitle(variableDeclaration.Parent)); } else { ReportDiagnostic(context, variableDeclarator, CSharpFacts.GetTitle(variableDeclaration.Parent)); } } else { ReportDiagnostic(context, node, CSharpFacts.GetTitle(node)); } } }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, SyntaxToken modifier) { SyntaxNode node = modifier.Parent; if (node.IsKind(SyntaxKind.DestructorDeclaration)) { return; } ModifierListInfo modifiersInfo = SyntaxInfo.ModifierListInfo(node); if (node.IsKind( SyntaxKind.ClassDeclaration, SyntaxKind.InterfaceDeclaration, SyntaxKind.StructDeclaration, SyntaxKind.RecordStructDeclaration)) { 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 AvailableAccessibilities) { if (accessibility != modifiersInfo.ExplicitAccessibility && SyntaxAccessibility.IsValidAccessibility(node, accessibility)) { context.RegisterRefactoring( GetTitle(accessibility), ct => RefactorAsync(context.Solution, memberDeclarations, accessibility, ct), RefactoringDescriptors.ChangeAccessibility, accessibility.ToString()); } } return; } } foreach (Accessibility accessibility in AvailableAccessibilities) { if (accessibility == modifiersInfo.ExplicitAccessibility) { continue; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol symbol = GetBaseSymbolOrDefault(semanticModel, context.CancellationToken); if (symbol != null) { if (SyntaxAccessibility.IsValidAccessibility(node, accessibility, ignoreOverride: true)) { context.RegisterRefactoring( GetTitle(accessibility), ct => RefactorAsync(context.Solution, symbol, accessibility, ct), RefactoringDescriptors.ChangeAccessibility, accessibility.ToString()); } } else if (SyntaxAccessibility.IsValidAccessibility(node, accessibility)) { context.RegisterRefactoring( GetTitle(accessibility), ct => RefactorAsync(context.Document, node, accessibility, ct), RefactoringDescriptors.ChangeAccessibility, accessibility.ToString()); } } ISymbol GetBaseSymbolOrDefault(SemanticModel semanticModel, CancellationToken cancellationToken) { if (modifiersInfo.GetFilter().HasAnyFlag(ModifierFilter.AbstractVirtualOverride)) { return(ChangeAccessibilityRefactoring.GetBaseSymbolOrDefault(node, semanticModel, cancellationToken)); } return(null); } }
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; } } } }
private static void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context, TypeDeclarationSyntax typeDeclaration, INamedTypeSymbol debuggerDisplayAttribute) { if (typeDeclaration.Modifiers.Contains(SyntaxKind.PartialKeyword)) { return; } SyntaxList <MemberDeclarationSyntax> members = typeDeclaration.Members; UnusedMemberWalker walker = null; foreach (MemberDeclarationSyntax member in members) { if (member.ContainsDiagnostics) { continue; } if (member.ContainsDirectives) { continue; } switch (member.Kind()) { case SyntaxKind.DelegateDeclaration: { var declaration = (DelegateDeclarationSyntax)member; if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddDelegate(declaration.Identifier.ValueText, declaration); } break; } case SyntaxKind.EventDeclaration: { var declaration = (EventDeclarationSyntax)member; if (declaration.ExplicitInterfaceSpecifier == null && SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(declaration.Identifier.ValueText, declaration); } break; } case SyntaxKind.EventFieldDeclaration: { var declaration = (EventFieldDeclarationSyntax)member; if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNodes(declaration.Declaration); } break; } case SyntaxKind.FieldDeclaration: { var declaration = (FieldDeclarationSyntax)member; SyntaxTokenList modifiers = declaration.Modifiers; if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNodes(declaration.Declaration, isConst: modifiers.Contains(SyntaxKind.ConstKeyword)); } break; } case SyntaxKind.MethodDeclaration: { var declaration = (MethodDeclarationSyntax)member; SyntaxTokenList modifiers = declaration.Modifiers; if (declaration.ExplicitInterfaceSpecifier == null && !declaration.AttributeLists.Any() && SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { string methodName = declaration.Identifier.ValueText; if (!IsMainMethod(declaration, modifiers, methodName)) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(methodName, declaration); } } break; } case SyntaxKind.PropertyDeclaration: { var declaration = (PropertyDeclarationSyntax)member; if (declaration.ExplicitInterfaceSpecifier == null && SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(declaration.Identifier.ValueText, declaration); } break; } } } if (walker == null) { return; } if (debuggerDisplayAttribute != null && walker.Nodes.Any(f => f.CanBeInDebuggerDisplayAttribute) && ShouldAnalyzeDebuggerDisplayAttribute()) { string value = context.SemanticModel .GetDeclaredSymbol(typeDeclaration, context.CancellationToken) .GetAttribute(debuggerDisplayAttribute)? .ConstructorArguments .SingleOrDefault(shouldThrow: false) .Value? .ToString(); if (value != null) { RemoveMethodsAndPropertiesThatAreInDebuggerDisplayAttributeValue(walker.Nodes, value); } if (walker.Nodes.Count == 0) { return; } } walker.Visit(typeDeclaration); foreach (NodeSymbolInfo info in UnusedMemberWalkerCache.GetNodesAndFree(walker)) { SyntaxNode node = info.Node; if (node is VariableDeclaratorSyntax variableDeclarator) { var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent; if (variableDeclaration.Variables.Count == 1) { ReportDiagnostic(context, variableDeclaration.Parent, CSharpFacts.GetTitle(variableDeclaration.Parent)); } else { ReportDiagnostic(context, variableDeclarator, CSharpFacts.GetTitle(variableDeclaration.Parent)); } } else { ReportDiagnostic(context, node, CSharpFacts.GetTitle(node)); } } bool ShouldAnalyzeDebuggerDisplayAttribute() { if (typeDeclaration.Modifiers.Contains(SyntaxKind.PartialKeyword)) { return(true); } foreach (AttributeListSyntax attributeList in typeDeclaration.AttributeLists) { foreach (AttributeSyntax attribute in attributeList.Attributes) { if (attribute.ArgumentList?.Arguments.Count(f => f.NameEquals == null) == 1) { return(true); } } } return(false); } }
public static void AnalyzeClassDeclaration(SyntaxNodeAnalysisContext context) { var classDeclaration = (ClassDeclarationSyntax)context.Node; if (!classDeclaration.Identifier.ValueText.EndsWith("Extensions", StringComparison.Ordinal)) { return; } if (!classDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword)) { return; } if (!classDeclaration.IsParentKind(SyntaxKind.NamespaceDeclaration, SyntaxKind.CompilationUnit)) { return; } if (!SyntaxAccessibility.GetAccessibility(classDeclaration).Is(Accessibility.Public, Accessibility.Internal)) { return; } foreach (MemberDeclarationSyntax member in classDeclaration.Members) { if (!member.IsKind(SyntaxKind.MethodDeclaration)) { continue; } var methodDeclaration = (MethodDeclarationSyntax)member; if (!methodDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword)) { continue; } if (!SyntaxAccessibility.GetAccessibility(methodDeclaration).Is(Accessibility.Public, Accessibility.Internal)) { continue; } ParameterSyntax parameter = methodDeclaration.ParameterList?.Parameters.FirstOrDefault(); if (parameter == null) { continue; } bool isThis = false; bool isIn = false; bool isRef = false; foreach (SyntaxToken modifier in parameter.Modifiers) { SyntaxKind kind = modifier.Kind(); if (kind == SyntaxKind.ThisKeyword) { isThis = true; break; } else if (kind == SyntaxKind.InKeyword) { isIn = true; } else if (kind == SyntaxKind.RefKeyword) { isRef = true; } if (isThis) { break; } } if (isThis) { continue; } if (isIn) { IParameterSymbol parameterSymbol = context.SemanticModel.GetDeclaredSymbol(parameter, context.CancellationToken); ITypeSymbol typeSymbol = parameterSymbol.Type; if (!typeSymbol.IsValueType) { continue; } if (typeSymbol.Kind == SymbolKind.TypeParameter) { continue; } } else if (isRef) { IParameterSymbol parameterSymbol = context.SemanticModel.GetDeclaredSymbol(parameter, context.CancellationToken); if (!parameterSymbol.Type.IsValueType) { continue; } } context.ReportDiagnostic(DiagnosticDescriptors.MakeMethodExtensionMethod, methodDeclaration.Identifier); } }
public static Task <Document> RefactorAsync( Document document, MemberDeclarationListSelection selectedMembers, Accessibility newAccessibility, CancellationToken cancellationToken) { SyntaxList <MemberDeclarationSyntax> newMembers = selectedMembers .UnderlyingList .ReplaceRange(selectedMembers.FirstIndex, selectedMembers.Count, selectedMembers.Select(f => SyntaxAccessibility.WithExplicitAccessibility(f, newAccessibility))); MemberDeclarationListInfo info = SyntaxInfo.MemberDeclarationListInfo(selectedMembers); return(document.ReplaceMembersAsync(info, newMembers, cancellationToken)); }