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

Commit 385ea90

Browse files
committed
Fixed exception with partial type with nested types
The code which queries for other partial members must use the original, unmodified, SyntaxNode. It is the only node which is guaranteed to be in the original tree and hence valid for uses with the semantic model.
1 parent f3fc4ae commit 385ea90

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,5 +340,29 @@ public partial class C { }
340340

341341
Verify(new[] { text1, text2 }, new[] { expected1, expected2 }, runFormatter: false);
342342
}
343+
344+
[Fact]
345+
public void PartialTypesWithNestedClasses()
346+
{
347+
var text = @"
348+
partial class C {
349+
class N1 { }
350+
class N2 { }
351+
}
352+
353+
public partial class C { }
354+
";
355+
356+
var expected = @"
357+
public partial class C {
358+
private class N1 { }
359+
private class N2 { }
360+
}
361+
362+
public partial class C { }
363+
";
364+
365+
Verify(text, expected, runFormatter: false);
366+
}
343367
}
344368
}

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,21 @@ internal VisibilityRewriter(Document document, CancellationToken cancellationTok
2929
_cancellationToken = cancellationToken;
3030
}
3131

32-
public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
32+
public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax originalNode)
3333
{
34-
node = (ClassDeclarationSyntax)base.VisitClassDeclaration(node);
35-
return EnsureVisibility(node, node.Modifiers, (x, l) => x.WithModifiers(l), () => GetTypeDefaultVisibility(node));
34+
var node = (ClassDeclarationSyntax)base.VisitClassDeclaration(originalNode);
35+
return EnsureVisibility(node, node.Modifiers, (x, l) => x.WithModifiers(l), () => GetTypeDefaultVisibility(originalNode));
3636
}
3737

3838
public override SyntaxNode VisitInterfaceDeclaration(InterfaceDeclarationSyntax node)
3939
{
4040
return EnsureVisibility(node, node.Modifiers, (x, l) => x.WithModifiers(l), () => GetTypeDefaultVisibility(node));
4141
}
4242

43-
public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax node)
43+
public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax originalNode)
4444
{
45-
node = (StructDeclarationSyntax)base.VisitStructDeclaration(node);
46-
return EnsureVisibility(node, node.Modifiers, (x, l) => x.WithModifiers(l), () => GetTypeDefaultVisibility(node));
45+
var node = (StructDeclarationSyntax)base.VisitStructDeclaration(originalNode);
46+
return EnsureVisibility(node, node.Modifiers, (x, l) => x.WithModifiers(l), () => GetTypeDefaultVisibility(originalNode));
4747
}
4848

4949
public override SyntaxNode VisitDelegateDeclaration(DelegateDeclarationSyntax node)
@@ -106,27 +106,27 @@ public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node)
106106
return EnsureVisibility(node, node.Modifiers, (x, l) => x.WithModifiers(l), () => SyntaxKind.PrivateKeyword);
107107
}
108108

109-
private SyntaxKind GetTypeDefaultVisibility(BaseTypeDeclarationSyntax node)
109+
private SyntaxKind GetTypeDefaultVisibility(BaseTypeDeclarationSyntax originalDeclarationSyntax)
110110
{
111111
// In the case of partial types we need to use the existing visibility if it exists
112-
if (node.Modifiers.Any(x => x.CSharpContextualKind() == SyntaxKind.PartialKeyword))
112+
if (originalDeclarationSyntax.Modifiers.Any(x => x.CSharpContextualKind() == SyntaxKind.PartialKeyword))
113113
{
114-
SyntaxKind? kind = GetExistingPartialVisibility(node);
114+
SyntaxKind? kind = GetExistingPartialVisibility(originalDeclarationSyntax);
115115
if (kind.HasValue)
116116
{
117117
return kind.Value;
118118
}
119119
}
120120

121-
return GetDelegateTypeDefaultVisibility(node);
121+
return GetDelegateTypeDefaultVisibility(originalDeclarationSyntax);
122122
}
123123

124124
private SyntaxKind GetDelegateTypeDefaultVisibility(SyntaxNode node)
125125
{
126126
return IsNestedDeclaration(node) ? SyntaxKind.PrivateKeyword : SyntaxKind.InternalKeyword;
127127
}
128128

129-
private SyntaxKind? GetExistingPartialVisibility(BaseTypeDeclarationSyntax declarationSyntax)
129+
private SyntaxKind? GetExistingPartialVisibility(BaseTypeDeclarationSyntax originalDeclarationSyntax)
130130
{
131131
// Getting the SemanticModel is a relatively expensive operation. Can take a few seconds in
132132
// projects of significant size. It is delay created to avoid this in files which already
@@ -136,7 +136,7 @@ private SyntaxKind GetDelegateTypeDefaultVisibility(SyntaxNode node)
136136
_semanticModel = _document.GetSemanticModelAsync(_cancellationToken).Result;
137137
}
138138

139-
var symbol = _semanticModel.GetDeclaredSymbol(declarationSyntax, _cancellationToken);
139+
var symbol = _semanticModel.GetDeclaredSymbol(originalDeclarationSyntax, _cancellationToken);
140140
if (symbol == null)
141141
{
142142
return null;

0 commit comments

Comments
 (0)