Skip to content
This repository was archived by the owner on Jul 12, 2022. It is now read-only.

Commit 23b723f

Browse files
committed
Added remaining visibility checks
This adds support for properties, fields, constructors and events.
1 parent a89aa10 commit 23b723f

File tree

2 files changed

+170
-1
lines changed

2 files changed

+170
-1
lines changed

src/Microsoft.DotNet.CodeFormatting.Tests/Rules/ExplicitVisibilityRuleTests.cs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,130 @@ internal interface I
111111

112112
Verify(text, expected, runFormatter: false);
113113
}
114+
115+
[Fact]
116+
public void TestExplicitInterfaceImplementation()
117+
{
118+
var text = @"
119+
interface I1
120+
{
121+
int Prop { get; set; }
122+
void M();
123+
}
124+
125+
class C : I1
126+
{
127+
int I1.Prop
128+
{
129+
get { return 0; }
130+
set { }
131+
}
132+
void I1.M() { }
133+
}
134+
";
135+
136+
var expected = @"
137+
internal interface I1
138+
{
139+
int Prop { get; set; }
140+
void M();
141+
}
142+
143+
internal class C : I1
144+
{
145+
int I1.Prop
146+
{
147+
get { return 0; }
148+
set { }
149+
}
150+
void I1.M() { }
151+
}
152+
";
153+
154+
Verify(text, expected, runFormatter: false);
155+
}
156+
157+
[Fact]
158+
public void TestFieldImplementation()
159+
{
160+
var text = @"
161+
class C
162+
{
163+
const int Max;
164+
int Field1;
165+
public int Field2;
166+
event EventHandler E1;
167+
public event EventHandler E2;
168+
}
169+
170+
struct C
171+
{
172+
const int Max;
173+
int Field1;
174+
public int Field2;
175+
event EventHandler E1;
176+
public event EventHandler E2;
177+
}
178+
";
179+
180+
var expected = @"
181+
internal class C
182+
{
183+
private const int Max;
184+
private int Field1;
185+
public int Field2;
186+
private event EventHandler E1;
187+
public event EventHandler E2;
188+
}
189+
190+
internal struct C
191+
{
192+
private const int Max;
193+
private int Field1;
194+
public int Field2;
195+
private event EventHandler E1;
196+
public event EventHandler E2;
197+
}
198+
";
199+
200+
Verify(text, expected, runFormatter: false);
201+
}
202+
203+
[Fact]
204+
public void TestConstructor()
205+
{
206+
var text = @"
207+
class C
208+
{
209+
static C() { }
210+
C() { }
211+
internal C(int p) { }
212+
}
213+
214+
struct S
215+
{
216+
static S() { }
217+
S(int p) { }
218+
internal S(int p1, int p2) { }
219+
}
220+
";
221+
var expected = @"
222+
internal class C
223+
{
224+
static C() { }
225+
private C() { }
226+
internal C(int p) { }
227+
}
228+
229+
internal struct S
230+
{
231+
static S() { }
232+
private S(int p) { }
233+
internal S(int p1, int p2) { }
234+
}
235+
";
236+
237+
Verify(text, expected, runFormatter: false);
238+
}
114239
}
115240
}

src/Microsoft.DotNet.CodeFormatting/Rules/ExplicitVisibilityRule.cs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Microsoft.DotNet.CodeFormatting.Rules
1313
{
14+
[RuleOrder(12)]
1415
internal sealed class ExplicitVisibilityRule : IFormattingRule
1516
{
1617
private sealed class VisibilityRewriter : CSharpSyntaxRewriter
@@ -47,9 +48,48 @@ public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node)
4748
return EnsureVisibility(node, node.Modifiers, (x, l) => x.WithModifiers(l), visibilityKind);
4849
}
4950

51+
public override SyntaxNode VisitConstructorDeclaration(ConstructorDeclarationSyntax node)
52+
{
53+
if (node.Modifiers.Any(x => x.CSharpKind() == SyntaxKind.StaticKeyword))
54+
{
55+
return node;
56+
}
57+
58+
return EnsureVisibility(node, node.Modifiers, (x, l) => x.WithModifiers(l), SyntaxKind.PrivateKeyword);
59+
}
60+
5061
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
5162
{
52-
node = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node);
63+
if (node.ExplicitInterfaceSpecifier != null)
64+
{
65+
return node;
66+
}
67+
68+
return EnsureVisibility(node, node.Modifiers, (x, l) => x.WithModifiers(l), SyntaxKind.PrivateKeyword);
69+
}
70+
71+
public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
72+
{
73+
if (node.ExplicitInterfaceSpecifier != null)
74+
{
75+
return node;
76+
}
77+
78+
return EnsureVisibility(node, node.Modifiers, (x, l) => x.WithModifiers(l), SyntaxKind.PrivateKeyword);
79+
}
80+
81+
public override SyntaxNode VisitEventDeclaration(EventDeclarationSyntax node)
82+
{
83+
return EnsureVisibility(node, node.Modifiers, (x, l) => x.WithModifiers(l), SyntaxKind.PrivateKeyword);
84+
}
85+
86+
public override SyntaxNode VisitEventFieldDeclaration(EventFieldDeclarationSyntax node)
87+
{
88+
return EnsureVisibility(node, node.Modifiers, (x, l) => x.WithModifiers(l), SyntaxKind.PrivateKeyword);
89+
}
90+
91+
public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node)
92+
{
5393
return EnsureVisibility(node, node.Modifiers, (x, l) => x.WithModifiers(l), SyntaxKind.PrivateKeyword);
5494
}
5595

@@ -74,6 +114,10 @@ private static bool IsNestedDeclaration(SyntaxNode node)
74114
return false;
75115
}
76116

117+
/// <summary>
118+
/// Return a node declaration that has a visibility modifier. If one isn't present it will be added as the
119+
/// first modifier. Any trivia before the node will be added as leading trivia to the added <see cref="SyntaxToken"/>.
120+
/// </summary>
77121
private static MemberDeclarationSyntax EnsureVisibility<T>(T node, SyntaxTokenList originalModifiers, Func<T, SyntaxTokenList, T> withModifiers, SyntaxKind visibilityKind) where T : MemberDeclarationSyntax
78122
{
79123
Debug.Assert(SyntaxFacts.IsAccessibilityModifier(visibilityKind));

0 commit comments

Comments
 (0)