Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
josefpihrt committed Jan 25, 2024
1 parent d9e8b17 commit 0e63c12
Show file tree
Hide file tree
Showing 2 changed files with 237 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) .NET Foundation and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Roslynator.CSharp.Syntax;

namespace Roslynator.CSharp.Analysis;

internal static class UseStringInterpolationInsteadOfStringConcatAnalysis
{
internal static void Analyze(SyntaxNodeAnalysisContext context, SimpleMemberInvocationExpressionInfo invocationInfo)
{
ISymbol symbol = context.SemanticModel.GetSymbol(invocationInfo.InvocationExpression, context.CancellationToken);

if (symbol?.Name == "Concat"
&& symbol.IsStatic
&& symbol.ContainingType.IsString())
{
bool? isVerbatim = null;

foreach (ArgumentSyntax argument in invocationInfo.Arguments)
{
ExpressionSyntax expression = argument.Expression;

if (expression.IsKind(SyntaxKind.InterpolatedStringExpression))
return;

if (expression.IsKind(SyntaxKind.StringLiteralExpression))
{
var literalExpression = (LiteralExpressionSyntax)expression;

if (literalExpression.Token.Text.StartsWith("@"))
{
if (isVerbatim is null)
{
isVerbatim = true;
}
else if (isVerbatim == false)
{
return;
}
}
else if (isVerbatim is null)
{
isVerbatim = false;
}
else if (isVerbatim == true)
{
return;
}
}
}

if (isVerbatim is not null
&& invocationInfo.ArgumentList.IsSingleLine())
{
DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UseStringInterpolationInsteadOfStringConcat, invocationInfo.InvocationExpression);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// Copyright (c) .NET Foundation and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Roslynator.CSharp.CodeFixes;
using Roslynator.Testing.CSharp;
using Xunit;

namespace Roslynator.CSharp.Analysis.Tests;

public class RCS1267UseStringInterpolationInsteadOfStringConcatTests : AbstractCSharpDiagnosticVerifier<InvocationExpressionAnalyzer, InvocationExpressionCodeFixProvider>
{
public override DiagnosticDescriptor Descriptor { get; } = DiagnosticRules.UseStringInterpolationInsteadOfStringConcat;

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseStringInterpolationInsteadOfStringConcat)]
public async Task Test()
{
await VerifyDiagnosticAndFixAsync("""
using System;

class C
{
void M()
{
string s = [|string.Concat("Now: ", DateTime.Now, ", Now UTC: ", DateTime.UtcNow)|];
}
}
""", """
using System;

class C
{
void M()
{
string s = $"Now: {DateTime.Now}, Now UTC: {DateTime.UtcNow}";
}
}
"""
);
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseStringInterpolationInsteadOfStringConcat)]
public async Task Test_Verbatim()
{
await VerifyDiagnosticAndFixAsync("""
using System;

class C
{
void M()
{
string s = [|string.Concat(@"Now: ", DateTime.Now, @", Now UTC: ", DateTime.UtcNow)|];
}
}
""", """
using System;

class C
{
void M()
{
string s = @$"Now: {DateTime.Now}, Now UTC: {DateTime.UtcNow}";
}
}
"""
);
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseStringInterpolationInsteadOfStringConcat)]
public async Task TestNoDiagnostic_SingleArgument()
{
await VerifyNoDiagnosticAsync("""
using System;

class C
{
void M()
{
string s = string.Concat("");
}
}
"""
);
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseStringInterpolationInsteadOfStringConcat)]
public async Task TestNoDiagnostic_NoStringLiteral()
{
await VerifyNoDiagnosticAsync("""
using System;

class C
{
void M()
{
string s = string.Concat(DateTime.Now, DateTime.Now);
}
}
"""
);
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseStringInterpolationInsteadOfStringConcat)]
public async Task TestNoDiagnostic_ContainsInterpolatedString()
{
await VerifyNoDiagnosticAsync("""
using System;

class C
{
void M()
{
string s = string.Concat(DateTime.Now, "", $"");
}
}
"""
);
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseStringInterpolationInsteadOfStringConcat)]
public async Task TestNoDiagnostic_ContainsVerbatimAndNonVerbatimLiterals()
{
await VerifyNoDiagnosticAsync("""
using System;

class C
{
void M()
{
string s = string.Concat(DateTime.Now, "", @"");
}
}
"""
);
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseStringInterpolationInsteadOfStringConcat)]
public async Task TestNoDiagnostic_ContainsVerbatimAndNonVerbatimLiterals2()
{
await VerifyNoDiagnosticAsync("""
using System;

class C
{
void M()
{
string s = string.Concat(DateTime.Now, @"", "");
}
}
"""
);
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseStringInterpolationInsteadOfStringConcat)]
public async Task TestNoDiagnostic_SpansOverMultipleLines()
{
await VerifyNoDiagnosticAsync("""
using System;

class C
{
void M()
{
string s = string.Concat(
"Now: ",
DateTime.Now,
", Now UTC: ",
DateTime.UtcNow);
}
}
"""
);
}
}

0 comments on commit 0e63c12

Please sign in to comment.