Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
a3852a6
added more conditions
RalfKoban Sep 9, 2024
46e03b5
Updated for patterns and if statements
RalfKoban Oct 11, 2025
6bfacc0
Tests fixed, code reformatted, duplicate expressions removed as they …
RalfKoban Oct 11, 2025
8eb0f9e
Merge commit 'bc0cea7' from master
RalfKoban Oct 11, 2025
00364d8
Merge commit '9ded308'
RalfKoban Oct 11, 2025
c83b014
Merge commit '41aaf8d'
RalfKoban Oct 13, 2025
df3e78b
Merge commit '5da691b'
RalfKoban Nov 1, 2025
133b82d
Merge commit '123a7c0'
RalfKoban Nov 1, 2025
7dd7865
Merge commit 'cde6061'
RalfKoban Nov 18, 2025
6496161
Merge commit 'fa4a902'
RalfKoban Nov 22, 2025
4017393
Merge commit '806b8ab'
RalfKoban Nov 30, 2025
f875251
Merge commit '5427773'
RalfKoban Dec 6, 2025
473eaa2
Merge commit 'd8b0b02'
RalfKoban Dec 8, 2025
9fb2fcd
Merge commit '88bbf32'
RalfKoban Dec 11, 2025
4c027a0
Merge commit '88fda8f'
RalfKoban Dec 12, 2025
8bb2639
Merge commit '8a277b7'
RalfKoban Jan 6, 2026
88f6eca
Merge commit '5553f6e'
RalfKoban Jan 15, 2026
71e134c
Merge commit 'e401281'
RalfKoban Jan 23, 2026
fd4d546
Merge commit '54a6209'
RalfKoban Jan 28, 2026
1ac1ef0
Merge commit '5a2e478'
RalfKoban Feb 10, 2026
1d22ca9
Merge commit '5ab1256'
RalfKoban Feb 14, 2026
31c358a
Merge commit '6777f25'
RalfKoban Feb 21, 2026
abe5910
Merge commit 'c99cc18'
RalfKoban Mar 3, 2026
73b53f7
Merge commit '7093fff'
RalfKoban Mar 3, 2026
1f6836a
Merge commit '3aaf48e'
RalfKoban Mar 9, 2026
83f438d
Merge commit '83785d0'
RalfKoban Mar 17, 2026
c1ed6f3
Merge commit '2628a84'
RalfKoban Mar 24, 2026
84e1079
Merge commit '7c40deb'
RalfKoban Apr 5, 2026
2a52d54
Merge commit '4090f41'
RalfKoban Apr 13, 2026
ddfca30
Merge commit '60ba751'
RalfKoban Apr 13, 2026
9289300
Merge commit '05b0586'
RalfKoban Apr 21, 2026
1623fbb
Merge commit 'c4024f9'
RalfKoban Apr 28, 2026
8e60952
Merge commit '685ccbc'
RalfKoban Apr 30, 2026
b3e92f7
Merge commit '5885fb1'
RalfKoban May 7, 2026
ce1b03f
Merge commit '4fa8e4d'
RalfKoban May 15, 2026
621908d
Merge commit 'f0c4a6d'
RalfKoban May 21, 2026
e6749e2
Merge commit '615b06d'
RalfKoban May 28, 2026
fbfe581
Merge commit '4bd4f42'
RalfKoban Jun 5, 2026
46e8c96
Merge commit 'dd4923f'
RalfKoban Jun 8, 2026
d72dbc4
Merge commit '408dd3c'
RalfKoban Jun 16, 2026
6660503
Merge commit '9e7fab9'
RalfKoban Jul 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,29 @@ public sealed class MiKo_6048_LogicalConditionsAreOnSameLineAnalyzer : SpacingAn

private static readonly SyntaxKind[] Expressions =
{
SyntaxKind.AddExpression,
SyntaxKind.AsExpression,
SyntaxKind.BitwiseAndExpression,
SyntaxKind.BitwiseOrExpression,
SyntaxKind.CoalesceExpression,
SyntaxKind.DivideExpression,
SyntaxKind.EqualsExpression,
SyntaxKind.ExclusiveOrExpression,
SyntaxKind.GreaterThanExpression,
SyntaxKind.GreaterThanOrEqualExpression,
SyntaxKind.IsExpression,
SyntaxKind.IsPatternExpression,
SyntaxKind.LeftShiftExpression,
SyntaxKind.LessThanExpression,
SyntaxKind.LessThanOrEqualExpression,
SyntaxKind.LogicalAndExpression,
SyntaxKind.LogicalOrExpression,
SyntaxKind.ModuloExpression,
SyntaxKind.MultiplyExpression,
SyntaxKind.NotEqualsExpression,
SyntaxKind.ParenthesizedExpression,
SyntaxKind.RightShiftExpression,
SyntaxKind.SubtractExpression,
};

public MiKo_6048_LogicalConditionsAreOnSameLineAnalyzer() : base(Id)
Expand All @@ -29,7 +50,7 @@ private static bool IsOnSingleLineLocal(SyntaxNode s)
return span.StartLinePosition.Line == span.EndLinePosition.Line;
}

private static bool IsOnSingleLine(ExpressionSyntax syntax)
private static bool IsOnSingleLine(SyntaxNode syntax)
{
switch (syntax)
{
Expand All @@ -39,6 +60,9 @@ private static bool IsOnSingleLine(ExpressionSyntax syntax)
case BinaryExpressionSyntax binary:
return IsOnSingleLine(binary);

case IsPatternExpressionSyntax isPattern:
return IsOnSingleLine(isPattern);

default:
return IsOnSingleLineLocal(syntax);
}
Expand Down Expand Up @@ -71,7 +95,7 @@ private static bool IsOnSingleLine(BinaryExpressionSyntax binary)
}

// they span different lines
return IsOnSingleLine(leftCondition) && IsOnSingleLine(rightCondition);
return false;
}

private static bool IsOnSingleLine(ParenthesizedExpressionSyntax parenthesized)
Expand All @@ -91,7 +115,37 @@ private static bool IsOnSingleLine(ParenthesizedExpressionSyntax parenthesized)
return false;
}

private static bool ShallAnalyzeNode(BinaryExpressionSyntax syntax)
private static bool IsOnSingleLine(IsPatternExpressionSyntax isPattern)
{
if (IsOnSingleLineLocal(isPattern))
{
return true;
}

var leftCondition = isPattern.Expression;
var rightCondition = isPattern.Pattern;

var leftSpan = leftCondition.GetLocation().GetLineSpan();
var rightSpan = rightCondition.GetLocation().GetLineSpan();

// let's see if both conditions are on same line
if (leftSpan.EndLinePosition.Line == rightSpan.StartLinePosition.Line)
{
if (leftSpan.StartLinePosition.Line == rightSpan.EndLinePosition.Line)
{
// both are on same line
return true;
}

// at least one condition spans multiple lines
return false;
}

// they span different lines
return false;
}

private static bool ShallAnalyzeNode(ExpressionSyntax syntax)
{
switch (syntax.Parent)
{
Expand All @@ -106,7 +160,7 @@ private static bool ShallAnalyzeNode(BinaryExpressionSyntax syntax)

private void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
if (context.Node is BinaryExpressionSyntax syntax && ShallAnalyzeNode(syntax))
if (context.Node is ExpressionSyntax syntax && ShallAnalyzeNode(syntax))
{
if (IsOnSingleLine(syntax))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void DoSomething(bool flag1, bool flag2)
");

[Test]
public void No_issue_is_reported_if_logical_condition_parts_are_all_on_their_own_line_with_condition_on_same_line_as_first() => No_issue_is_reported_for(@"
public void An_issue_is_reported_if_logical_condition_parts_are_all_on_their_own_line_with_condition_on_same_line_as_first() => An_issue_is_reported_for(@"
using System;

public class TestMe
Expand All @@ -41,7 +41,7 @@ public void DoSomething(bool flag1, bool flag2)
");

[Test]
public void No_issue_is_reported_if_logical_condition_parts_are_all_on_their_own_line_with_condition_on_same_line_as_last() => No_issue_is_reported_for(@"
public void An_issue_is_reported_if_logical_condition_parts_are_all_on_their_own_line_with_condition_on_same_line_as_last() => An_issue_is_reported_for(@"
using System;

public class TestMe
Expand All @@ -56,7 +56,7 @@ public void DoSomething(bool flag1, bool flag2)
");

[Test]
public void No_issue_is_reported_if_multiple_logical_condition_parts_are_all_on_their_own_lines() => No_issue_is_reported_for(@"
public void An_issue_is_reported_if_multiple_logical_condition_parts_are_all_on_their_own_lines() => An_issue_is_reported_for(@"
using System;

public class TestMe
Expand All @@ -75,7 +75,7 @@ public void DoSomething(bool flag1, bool flag2, bool flag3, bool flag4)
");

[Test]
public void No_issue_is_reported_if_parenthesized_logical_condition_parts_are_all_on_their_own_line_and_combined_condition_is_first() => No_issue_is_reported_for(@"
public void An_issue_is_reported_if_parenthesized_logical_condition_parts_are_all_on_their_own_line_and_combined_condition_is_first() => An_issue_is_reported_for(@"
using System;

public class TestMe
Expand All @@ -90,7 +90,7 @@ public void DoSomething(bool flag1, bool flag2, bool flag3)
");

[Test]
public void No_issue_is_reported_if_parenthesized_logical_condition_parts_are_all_on_their_own_line_and_combined_condition_is_last() => No_issue_is_reported_for(@"
public void An_issue_is_reported_if_parenthesized_logical_condition_parts_are_all_on_their_own_line_and_combined_condition_is_last() => An_issue_is_reported_for(@"
using System;

public class TestMe
Expand All @@ -105,7 +105,7 @@ public void DoSomething(bool flag1, bool flag2, bool flag3)
");

[Test]
public void No_issue_is_reported_if_multiple_parenthesized_logical_condition_parts_are_all_on_multiple_lines() => No_issue_is_reported_for(@"
public void An_issue_is_reported_if_multiple_parenthesized_logical_condition_parts_are_all_on_multiple_lines() => An_issue_is_reported_for(@"
using System;

public class TestMe
Expand Down Expand Up @@ -467,6 +467,187 @@ public class TestMe
VerifyCSharpFix(OriginalCode, FixedCode);
}

[TestCase("\r\n == null", "== null")]
[TestCase("== \r\n null", "== null")]
[TestCase("\r\n != null", "!= null")]
[TestCase("!= \r\n null", "!= null")]
[TestCase("\r\n is null", "is null")]
[TestCase("is \r\n null", "is null")]
[TestCase("\r\n is not null", "is not null")]
[TestCase("is \r\n not null", "is not null")]
[TestCase("is not \r\n null", "is not null")]
public void Code_gets_fixed_for_logical_condition_(string originalCondition, string fixedCondition)
{
const string Template = @"
using System;

public class TestMe
{
public object SomeProperty { get; set; }

public void DoSomething(object o)
{
if (SomeProperty ###)
{ }
}
}
";

VerifyCSharpFix(Template.Replace("###", originalCondition), Template.Replace("###", fixedCondition));
}

[Test]
public void Code_gets_fixed_if_logical_condition_with_equality_conditions_as_logical_parts_are_on_different_lines_1()
{
const string OriginalCode = @"
using System;

public class TestMe
{
public object SomeProperty { get; set; }

public void DoSomething(object o)
{
if (SomeProperty != null
&& SomeProperty.Equals(o))
{ }
}
}
";

const string FixedCode = @"
using System;

public class TestMe
{
public object SomeProperty { get; set; }

public void DoSomething(object o)
{
if (SomeProperty != null && SomeProperty.Equals(o))
{ }
}
}
";

VerifyCSharpFix(OriginalCode, FixedCode);
}

[Test]
public void Code_gets_fixed_if_logical_condition_with_equality_conditions_as_logical_parts_are_on_different_lines_2()
{
const string OriginalCode = @"
using System;

public class TestMe
{
public object SomeProperty { get; set; }

public void DoSomething(object o)
{
if (SomeProperty
!= null
&& SomeProperty.Equals(o))
{ }
}
}
";

const string FixedCode = @"
using System;

public class TestMe
{
public object SomeProperty { get; set; }

public void DoSomething(object o)
{
if (SomeProperty != null && SomeProperty.Equals(o))
{ }
}
}
";

VerifyCSharpFix(OriginalCode, FixedCode);
}

[Test]
public void Code_gets_fixed_if_logical_condition_with_equality_conditions_as_logical_parts_are_on_different_lines_3()
{
const string OriginalCode = @"
using System;

public class TestMe
{
public object SomeProperty { get; set; }

public void DoSomething(object o)
{
if (SomeProperty
!=
null
&& SomeProperty.Equals(o))
{ }
}
}
";

const string FixedCode = @"
using System;

public class TestMe
{
public object SomeProperty { get; set; }

public void DoSomething(object o)
{
if (SomeProperty != null && SomeProperty.Equals(o))
{ }
}
}
";

VerifyCSharpFix(OriginalCode, FixedCode);
}

[Test]
public void Code_gets_fixed_if_logical_condition_with_equality_conditions_as_logical_parts_are_on_different_lines_4()
{
const string OriginalCode = @"
using System;

public class TestMe
{
public object SomeProperty { get; set; }

public void DoSomething(object o)
{
if (SomeProperty != null
&& SomeProperty
.Equals(o))
{ }
}
}
";

const string FixedCode = @"
using System;

public class TestMe
{
public object SomeProperty { get; set; }

public void DoSomething(object o)
{
if (SomeProperty != null && SomeProperty.Equals(o))
{ }
}
}
";

VerifyCSharpFix(OriginalCode, FixedCode);
}

[Test]
public void Code_gets_fixed_for_invocation_on_multiple_lines()
{
Expand Down