Skip to content

Commit

Permalink
Use extra generic type parameters and apply C#-specific knowledge to …
Browse files Browse the repository at this point in the history
…all langs instead of using inheritance
  • Loading branch information
jnm2 committed Nov 29, 2020
1 parent 5949b49 commit 4365779
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 56 deletions.
1 change: 0 additions & 1 deletion src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
<Compile Include="$(MSBuildThisFileDirectory)RemoveUnreachableCode\CSharpRemoveUnreachableCodeDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)RemoveUnreachableCode\RemoveUnreachableCodeHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SimplifyBooleanExpression\CSharpSimplifyConditionalDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SimplifyInterpolation\CSharpHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SimplifyInterpolation\CSharpSimplifyInterpolationDiagnosticAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UseAutoProperty\CSharpUseAutoPropertyAnalyzer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UseCoalesceExpression\CSharpUseCoalesceExpressionDiagnosticAnalyzer.cs" />
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#nullable disable

using Microsoft.CodeAnalysis.CSharp.Analyzers.SimplifyInterpolation;
using Microsoft.CodeAnalysis.CSharp.EmbeddedLanguages.VirtualChars;
using Microsoft.CodeAnalysis.CSharp.LanguageServices;
using Microsoft.CodeAnalysis.CSharp.Syntax;
Expand All @@ -17,14 +16,12 @@ namespace Microsoft.CodeAnalysis.CSharp.SimplifyInterpolation
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal class CSharpSimplifyInterpolationDiagnosticAnalyzer : AbstractSimplifyInterpolationDiagnosticAnalyzer<
InterpolationSyntax, ExpressionSyntax>
InterpolationSyntax, ExpressionSyntax, ConditionalExpressionSyntax, ParenthesizedExpressionSyntax>
{
protected override IVirtualCharService GetVirtualCharService()
=> CSharpVirtualCharService.Instance;

protected override ISyntaxFacts GetSyntaxFacts()
=> CSharpSyntaxFacts.Instance;

protected override Helpers GetHelpers() => new CSharpHelpers();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Text;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Analyzers.SimplifyInterpolation;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.SimplifyInterpolation;

Expand All @@ -17,16 +16,15 @@ namespace Microsoft.CodeAnalysis.CSharp.SimplifyInterpolation
[ExportCodeFixProvider(LanguageNames.CSharp), Shared]
internal class CSharpSimplifyInterpolationCodeFixProvider : AbstractSimplifyInterpolationCodeFixProvider<
InterpolationSyntax, ExpressionSyntax, InterpolationAlignmentClauseSyntax,
InterpolationFormatClauseSyntax, InterpolatedStringExpressionSyntax>
InterpolationFormatClauseSyntax, InterpolatedStringExpressionSyntax,
ConditionalExpressionSyntax, ParenthesizedExpressionSyntax>
{
[ImportingConstructor]
[SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification = "Used in test code: https://github.com/dotnet/roslyn/issues/42814")]
public CSharpSimplifyInterpolationCodeFixProvider()
{
}

protected override Helpers GetHelpers() => new CSharpHelpers();

protected override InterpolationSyntax WithExpression(InterpolationSyntax interpolation, ExpressionSyntax expression)
=> interpolation.WithExpression(expression);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ namespace Microsoft.CodeAnalysis.SimplifyInterpolation
{
internal abstract class AbstractSimplifyInterpolationDiagnosticAnalyzer<
TInterpolationSyntax,
TExpressionSyntax> : AbstractBuiltInCodeStyleDiagnosticAnalyzer
TExpressionSyntax,
TConditionalExpressionSyntax,
TParenthesizedExpressionSyntax> : AbstractBuiltInCodeStyleDiagnosticAnalyzer
where TInterpolationSyntax : SyntaxNode
where TExpressionSyntax : SyntaxNode
where TConditionalExpressionSyntax : TExpressionSyntax
where TParenthesizedExpressionSyntax : TExpressionSyntax
{
protected AbstractSimplifyInterpolationDiagnosticAnalyzer()
: base(IDEDiagnosticIds.SimplifyInterpolationId,
Expand All @@ -32,8 +36,6 @@ protected AbstractSimplifyInterpolationDiagnosticAnalyzer()

protected abstract ISyntaxFacts GetSyntaxFacts();

protected virtual Helpers GetHelpers() => new();

public override DiagnosticAnalyzerCategory GetAnalyzerCategory()
=> DiagnosticAnalyzerCategory.SemanticSpanAnalysis;

Expand All @@ -60,7 +62,7 @@ private void AnalyzeInterpolation(OperationAnalysisContext context)
return;
}

GetHelpers().UnwrapInterpolation<TInterpolationSyntax, TExpressionSyntax>(
Helpers.UnwrapInterpolation<TInterpolationSyntax, TExpressionSyntax, TConditionalExpressionSyntax, TParenthesizedExpressionSyntax>(
GetVirtualCharService(), GetSyntaxFacts(), interpolation, out _, out var alignment, out _,
out var formatString, out var unnecessaryLocations);

Expand Down
46 changes: 32 additions & 14 deletions src/Analyzers/Core/Analyzers/SimplifyInterpolation/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,28 @@

namespace Microsoft.CodeAnalysis.SimplifyInterpolation
{
internal class Helpers
internal static class Helpers
{
protected virtual SyntaxNode GetPreservedInterpolationExpressionSyntax(IOperation operation)
private static SyntaxNode GetPreservedInterpolationExpressionSyntax<TConditionalExpressionSyntax, TParenthesizedExpressionSyntax>(
IOperation operation)
where TConditionalExpressionSyntax : SyntaxNode
where TParenthesizedExpressionSyntax : SyntaxNode
{
return operation.Syntax;
return operation.Syntax switch
{
TConditionalExpressionSyntax { Parent: TParenthesizedExpressionSyntax parent } => parent,
var syntax => syntax,
};
}

public void UnwrapInterpolation<TInterpolationSyntax, TExpressionSyntax>(
public static void UnwrapInterpolation<TInterpolationSyntax, TExpressionSyntax, TConditionalExpressionSyntax, TParenthesizedExpressionSyntax>(
IVirtualCharService virtualCharService, ISyntaxFacts syntaxFacts, IInterpolationOperation interpolation,
out TExpressionSyntax? unwrapped, out TExpressionSyntax? alignment, out bool negate,
out string? formatString, out ImmutableArray<Location> unnecessaryLocations)
where TInterpolationSyntax : SyntaxNode
where TExpressionSyntax : SyntaxNode
where TInterpolationSyntax : SyntaxNode
where TExpressionSyntax : SyntaxNode
where TConditionalExpressionSyntax : TExpressionSyntax
where TParenthesizedExpressionSyntax : TExpressionSyntax
{
alignment = null;
negate = false;
Expand All @@ -37,15 +46,17 @@ public void UnwrapInterpolation<TInterpolationSyntax, TExpressionSyntax>(
var expression = Unwrap(interpolation.Expression);
if (interpolation.Alignment == null)
{
UnwrapAlignmentPadding(expression, out expression, out alignment, out negate, unnecessarySpans);
UnwrapAlignmentPadding<TExpressionSyntax, TConditionalExpressionSyntax, TParenthesizedExpressionSyntax>(
expression, out expression, out alignment, out negate, unnecessarySpans);
}

if (interpolation.FormatString == null)
{
UnwrapFormatString(virtualCharService, syntaxFacts, expression, out expression, out formatString, unnecessarySpans);
UnwrapFormatString<TConditionalExpressionSyntax, TParenthesizedExpressionSyntax>(
virtualCharService, syntaxFacts, expression, out expression, out formatString, unnecessarySpans);
}

unwrapped = GetPreservedInterpolationExpressionSyntax(expression) as TExpressionSyntax;
unwrapped = GetPreservedInterpolationExpressionSyntax<TConditionalExpressionSyntax, TParenthesizedExpressionSyntax>(expression) as TExpressionSyntax;

unnecessaryLocations =
unnecessarySpans.OrderBy(t => t.Start)
Expand All @@ -70,9 +81,11 @@ private static IOperation Unwrap(IOperation expression)
}
}

private void UnwrapFormatString(
private static void UnwrapFormatString<TConditionalExpressionSyntax, TParenthesizedExpressionSyntax>(
IVirtualCharService virtualCharService, ISyntaxFacts syntaxFacts, IOperation expression, out IOperation unwrapped,
out string? formatString, List<TextSpan> unnecessarySpans)
where TConditionalExpressionSyntax : SyntaxNode
where TParenthesizedExpressionSyntax : SyntaxNode
{
if (expression is IInvocationOperation { TargetMethod: { Name: nameof(ToString) } } invocation &&
HasNonImplicitInstance(invocation) &&
Expand All @@ -87,8 +100,9 @@ private void UnwrapFormatString(
unwrapped = invocation.Instance;
formatString = value;

var unwrappedSyntax = GetPreservedInterpolationExpressionSyntax<TConditionalExpressionSyntax, TParenthesizedExpressionSyntax>(unwrapped);
unnecessarySpans.AddRange(invocation.Syntax.Span
.Subtract(GetPreservedInterpolationExpressionSyntax(invocation.Instance).FullSpan)
.Subtract(unwrappedSyntax.FullSpan)
.Subtract(GetSpanWithinLiteralQuotes(virtualCharService, literal.Syntax.GetFirstToken())));
return;
}
Expand All @@ -107,8 +121,9 @@ private void UnwrapFormatString(
unwrapped = invocation.Instance;
formatString = "";

var unwrappedSyntax = GetPreservedInterpolationExpressionSyntax<TConditionalExpressionSyntax, TParenthesizedExpressionSyntax>(unwrapped);
unnecessarySpans.AddRange(invocation.Syntax.Span
.Subtract(GetPreservedInterpolationExpressionSyntax(invocation.Instance).FullSpan));
.Subtract(unwrappedSyntax.FullSpan));
return;
}
}
Expand All @@ -125,10 +140,12 @@ private static TextSpan GetSpanWithinLiteralQuotes(IVirtualCharService virtualCh
: TextSpan.FromBounds(sequence.First().Span.Start, sequence.Last().Span.End);
}

private void UnwrapAlignmentPadding<TExpressionSyntax>(
private static void UnwrapAlignmentPadding<TExpressionSyntax, TConditionalExpressionSyntax, TParenthesizedExpressionSyntax>(
IOperation expression, out IOperation unwrapped,
out TExpressionSyntax? alignment, out bool negate, List<TextSpan> unnecessarySpans)
where TExpressionSyntax : SyntaxNode
where TConditionalExpressionSyntax : TExpressionSyntax
where TParenthesizedExpressionSyntax : TExpressionSyntax
{
if (expression is IInvocationOperation invocation &&
HasNonImplicitInstance(invocation))
Expand All @@ -151,8 +168,9 @@ private void UnwrapAlignmentPadding<TExpressionSyntax>(
alignment = alignmentSyntax as TExpressionSyntax;
negate = targetName == nameof(string.PadRight);

var unwrappedSyntax = GetPreservedInterpolationExpressionSyntax<TConditionalExpressionSyntax, TParenthesizedExpressionSyntax>(unwrapped);
unnecessarySpans.AddRange(invocation.Syntax.Span
.Subtract(GetPreservedInterpolationExpressionSyntax(invocation.Instance).FullSpan)
.Subtract(unwrappedSyntax.FullSpan)
.Subtract(alignmentSyntax.FullSpan));
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,22 @@ internal abstract class AbstractSimplifyInterpolationCodeFixProvider<
TExpressionSyntax,
TInterpolationAlignmentClause,
TInterpolationFormatClause,
TInterpolatedStringExpressionSyntax> : SyntaxEditorBasedCodeFixProvider
TInterpolatedStringExpressionSyntax,
TConditionalExpressionSyntax,
TParenthesizedExpressionSyntax> : SyntaxEditorBasedCodeFixProvider
where TInterpolationSyntax : SyntaxNode
where TExpressionSyntax : SyntaxNode
where TInterpolationAlignmentClause : SyntaxNode
where TInterpolationFormatClause : SyntaxNode
where TInterpolatedStringExpressionSyntax : TExpressionSyntax
where TConditionalExpressionSyntax : TExpressionSyntax
where TParenthesizedExpressionSyntax : TExpressionSyntax
{
public override ImmutableArray<string> FixableDiagnosticIds { get; } =
ImmutableArray.Create(IDEDiagnosticIds.SimplifyInterpolationId);

internal override CodeFixCategory CodeFixCategory => CodeFixCategory.CodeStyle;

protected virtual Helpers GetHelpers() => new();

protected abstract TInterpolationSyntax WithExpression(TInterpolationSyntax interpolation, TExpressionSyntax expression);
protected abstract TInterpolationSyntax WithAlignmentClause(TInterpolationSyntax interpolation, TInterpolationAlignmentClause alignmentClause);
protected abstract TInterpolationSyntax WithFormatClause(TInterpolationSyntax interpolation, TInterpolationFormatClause? formatClause);
Expand All @@ -57,16 +59,14 @@ protected override async Task FixAllAsync(
var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var generator = editor.Generator;
var generatorInternal = document.GetRequiredLanguageService<SyntaxGeneratorInternal>();
var helpers = GetHelpers();

foreach (var diagnostic in diagnostics)
{
var loc = diagnostic.AdditionalLocations[0];
var interpolation = semanticModel.GetOperation(loc.FindNode(getInnermostNodeForTie: true, cancellationToken), cancellationToken) as IInterpolationOperation;
if (interpolation?.Syntax is TInterpolationSyntax interpolationSyntax &&
interpolationSyntax.Parent is TInterpolatedStringExpressionSyntax interpolatedString)
{
helpers.UnwrapInterpolation<TInterpolationSyntax, TExpressionSyntax>(
Helpers.UnwrapInterpolation<TInterpolationSyntax, TExpressionSyntax, TConditionalExpressionSyntax, TParenthesizedExpressionSyntax>(
document.GetRequiredLanguageService<IVirtualCharLanguageService>(),
document.GetRequiredLanguageService<ISyntaxFactsService>(), interpolation, out var unwrapped,
out var alignment, out var negate, out var formatString, out _);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.SimplifyInterpolation
<DiagnosticAnalyzer(LanguageNames.VisualBasic)>
Friend Class VisualBasicSimplifyInterpolationDiagnosticAnalyzer
Inherits AbstractSimplifyInterpolationDiagnosticAnalyzer(Of InterpolationSyntax, ExpressionSyntax)
Inherits AbstractSimplifyInterpolationDiagnosticAnalyzer(Of
InterpolationSyntax,
ExpressionSyntax,
TernaryConditionalExpressionSyntax,
ParenthesizedExpressionSyntax)

Protected Overrides Function GetVirtualCharService() As IVirtualCharService
Return VisualBasicVirtualCharService.Instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SimplifyInterpolation
Friend Class VisualBasicSimplifyInterpolationCodeFixProvider
Inherits AbstractSimplifyInterpolationCodeFixProvider(Of
InterpolationSyntax, ExpressionSyntax, InterpolationAlignmentClauseSyntax,
InterpolationFormatClauseSyntax, InterpolatedStringExpressionSyntax)
InterpolationFormatClauseSyntax, InterpolatedStringExpressionSyntax,
TernaryConditionalExpressionSyntax, ParenthesizedExpressionSyntax)

<ImportingConstructor>
<SuppressMessage("RoslynDiagnosticsReliability", "RS0033:Importing constructor should be [Obsolete]", Justification:="Used in test code: https://github.com/dotnet/roslyn/issues/42814")>
Expand Down

0 comments on commit 4365779

Please sign in to comment.