Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions docs/Rules/MA0028.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ new StringBuilder().Append("a" + 10);
new StringBuilder().Append("a").Append(10);
```

The concatenation of constant strings and chars (e.g. `" " + ConstChar + " "`) is not reported, as the compiler merges it into a single string.

```csharp
new StringBuilder().Append("a");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,16 @@ private static bool IsEquivalentAppendJoinOverload(IMethodSymbol joinMethod, IMe

private static bool IsConstString(IOperation operation)
{
return TryGetConstStringValue(operation, out _);
if (TryGetConstStringValue(operation, out _))
return true;

// The compiler merges the constant chars and strings of a concatenation into a single string (e.g. " " + 'c' + " ")
return operation switch
{
IConversionOperation { IsImplicit: true, Operand.ConstantValue: { HasValue: true, Value: char } } => true,
IBinaryOperation { OperatorKind: BinaryOperatorKind.Add } binaryOperation when binaryOperation.Type.IsString() => IsConstString(binaryOperation.LeftOperand) && IsConstString(binaryOperation.RightOperand),
_ => false,
};
}

private static bool TryGetConstStringValue(IOperation operation, [NotNullWhen(true)] out string? value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,10 @@ void A()
[InlineData(@"$""abc{""test""}""")]
[InlineData(@"""abc"" + ""test""")]
[InlineData(@"$""abc{""test""}"" + ""test""")]
[InlineData(@"""abc"" + 'd'")]
[InlineData(@"'a' + ""bc""")]
[InlineData(@""" "" + 'c' + "" """)]
[InlineData(@"""a"" + ('b' + ""c"")")]
public Task Append_NoDiagnostic(string text)
{
var test = CreateTest();
Expand All @@ -281,10 +285,28 @@ void A()
return test.RunAsync();
}

[Fact]
public Task Append_ConcatConstantChar_NoDiagnostic()
{
var test = CreateTest();
test.TestCode = """
using System.Text;
class Test
{
public const char Const = 'C';

string A() => new StringBuilder().Append(" " + Const + " ").AppendLine(" " + Const + " ").ToString();
}
""";

return test.RunAsync();
}

[Theory]
[InlineData(@"$""a{1}""")]
[InlineData(@"""a"" + 10")]
[InlineData(@"10 + 20 + ""a""")]
[InlineData(@"""a"" + 'b' + 10")]
[InlineData(@"""""")]
[InlineData(@""""" + """"")]
[InlineData(@""""".Substring(0, 10)")]
Expand Down
Loading