Skip to content

Commit b6e2036

Browse files
committed
Update SA1110 for target-typed new
1 parent ff14d11 commit b6e2036

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/ReadabilityRules/SA1110CSharp9UnitTests.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,48 @@ public async Task TestPrimaryConstructorBaseListWithoutParametersAsync(string ty
130130
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
131131
}
132132

133+
[Fact]
134+
[WorkItem(3972, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3972")]
135+
public async Task TestTargetTypedNewOpeningParenthesisOnNextLineAsync()
136+
{
137+
var testCode = @"
138+
class TestClass
139+
{
140+
public TestClass(int value)
141+
{
142+
}
143+
}
144+
145+
class Test
146+
{
147+
void M()
148+
{
149+
TestClass value = new
150+
{|#0:(|}1);
151+
}
152+
}";
153+
154+
var fixedCode = @"
155+
class TestClass
156+
{
157+
public TestClass(int value)
158+
{
159+
}
160+
}
161+
162+
class Test
163+
{
164+
void M()
165+
{
166+
TestClass value = new(
167+
1);
168+
}
169+
}";
170+
171+
var expected = Diagnostic().WithLocation(0);
172+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
173+
}
174+
133175
protected virtual DiagnosticResult[] GetExpectedResultTestPrimaryConstructor()
134176
{
135177
return new[]

StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1110OpeningParenthesisMustBeOnDeclarationLine.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ internal class SA1110OpeningParenthesisMustBeOnDeclarationLine : DiagnosticAnaly
6060
private static readonly Action<SyntaxNodeAnalysisContext> ConstructorDeclarationAction = HandleConstructorDeclaration;
6161
private static readonly Action<SyntaxNodeAnalysisContext> InvocationExpressionAction = HandleInvocationExpression;
6262
private static readonly Action<SyntaxNodeAnalysisContext> ObjectCreationExpressionAction = HandleObjectCreationExpression;
63+
private static readonly Action<SyntaxNodeAnalysisContext> ImplicitObjectCreationExpressionAction = HandleImplicitObjectCreationExpression;
6364
private static readonly Action<SyntaxNodeAnalysisContext> IndexerDeclarationAction = HandleIndexerDeclaration;
6465
private static readonly Action<SyntaxNodeAnalysisContext> ElementAccessExpressionAction = HandleElementAccessExpression;
6566
private static readonly Action<SyntaxNodeAnalysisContext> AttributeAction = HandleAttribute;
@@ -86,6 +87,7 @@ public override void Initialize(AnalysisContext context)
8687
context.RegisterSyntaxNodeAction(ConstructorDeclarationAction, SyntaxKind.ConstructorDeclaration);
8788
context.RegisterSyntaxNodeAction(InvocationExpressionAction, SyntaxKind.InvocationExpression);
8889
context.RegisterSyntaxNodeAction(ObjectCreationExpressionAction, SyntaxKind.ObjectCreationExpression);
90+
context.RegisterSyntaxNodeAction(ImplicitObjectCreationExpressionAction, SyntaxKindEx.ImplicitObjectCreationExpression);
8991
context.RegisterSyntaxNodeAction(IndexerDeclarationAction, SyntaxKind.IndexerDeclaration);
9092
context.RegisterSyntaxNodeAction(ElementAccessExpressionAction, SyntaxKind.ElementAccessExpression);
9193
context.RegisterSyntaxNodeAction(AttributeAction, SyntaxKind.Attribute);
@@ -258,6 +260,24 @@ private static void HandleObjectCreationExpression(SyntaxNodeAnalysisContext con
258260
}
259261
}
260262

263+
private static void HandleImplicitObjectCreationExpression(SyntaxNodeAnalysisContext context)
264+
{
265+
var implicitObjectCreation = (ImplicitObjectCreationExpressionSyntaxWrapper)context.Node;
266+
if (implicitObjectCreation.NewKeyword.IsMissing)
267+
{
268+
return;
269+
}
270+
271+
var argumentList = implicitObjectCreation.ArgumentList;
272+
273+
if (argumentList != null
274+
&& !argumentList.OpenParenToken.IsMissing)
275+
{
276+
bool preserveLayout = argumentList.Arguments.Any();
277+
CheckIfLocationOfPreviousTokenAndOpenTokenAreTheSame(context, argumentList.OpenParenToken, preserveLayout);
278+
}
279+
}
280+
261281
private static SyntaxToken? GetIdentifier(ObjectCreationExpressionSyntax objectCreationExpressionSyntax)
262282
{
263283
switch (objectCreationExpressionSyntax.Type.Kind())

documentation/SA1110.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ not placed on the same line as the method or indexer name.
2525
A violation of this rule occurs when the opening bracket of a method or indexer call or declaration is not placed on the
2626
same line as the method or indexer. The following examples show correct placement of the opening bracket:
2727

28+
This rule also applies to constructor invocations and object creation expressions, including target-typed `new` expressions
29+
introduced in C# 9. In all of these cases, the `(` should appear on the same line as the `new` keyword.
30+
2831
```csharp
2932
public string JoinName(string first, string last)
3033
{

0 commit comments

Comments
 (0)