Skip to content

Commit

Permalink
AtCoderAnalyzer_UseMethodImplNumeric
Browse files Browse the repository at this point in the history
  • Loading branch information
kzrnm committed May 31, 2022
1 parent 06fbbfe commit 7f58c8a
Show file tree
Hide file tree
Showing 18 changed files with 279 additions and 68 deletions.
12 changes: 8 additions & 4 deletions Source/AtCoderAnalyzer/AggressiveInliningCodeFixProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
is not CompilationUnitSyntax root)
return;

var config = AtCoderAnalyzerConfig.Parse(context.Document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GlobalOptions);
var diagnostic = context.Diagnostics[0];
var diagnosticSpan = diagnostic.Location.SourceSpan;

Expand All @@ -42,18 +43,19 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
return;

var action = CodeAction.Create(title: title,
createChangedDocument: c => AddAggressiveInlining(context.Document, root, diagnosticSpan.Start, typeDeclarationSyntax, c),
createChangedDocument: c => AddAggressiveInlining(context.Document, root, diagnosticSpan.Start, config, typeDeclarationSyntax, c),
equivalenceKey: title);
context.RegisterCodeFix(action, diagnostic);
}

private async Task<Document> AddAggressiveInlining(
Document document, CompilationUnitSyntax root,
int postion,
AtCoderAnalyzerConfig config,
TypeDeclarationSyntax typeDeclarationSyntax, CancellationToken cancellationToken)
{
root = root.ReplaceNode(typeDeclarationSyntax,
new AddAggressiveInliningRewriter(await document.GetSemanticModelAsync(cancellationToken), postion)
new AddAggressiveInliningRewriter(await document.GetSemanticModelAsync(cancellationToken), postion, config)
.Visit(typeDeclarationSyntax));

return document.WithSyntaxRoot(root);
Expand All @@ -66,15 +68,17 @@ private class AddAggressiveInliningRewriter : CSharpSyntaxRewriter
private readonly INamedTypeSymbol methodImplAttribute;
private readonly INamedTypeSymbol methodImplOptions;
private readonly AttributeSyntax aggressiveInliningAttribute;
public AddAggressiveInliningRewriter(SemanticModel semanticModel, int position) : base(false)
public AddAggressiveInliningRewriter(SemanticModel semanticModel, int position, AtCoderAnalyzerConfig config) : base(false)
{
this.semanticModel = semanticModel;
this.position = position;
methodImplAttribute = semanticModel.Compilation.GetTypeByMetadataName(
System_Runtime_CompilerServices_MethodImplAttribute);
methodImplOptions = semanticModel.Compilation.GetTypeByMetadataName(
System_Runtime_CompilerServices_MethodImplOptions);
aggressiveInliningAttribute = SyntaxHelpers.AggressiveInliningAttribute(methodImplAttribute.ToMinimalDisplayString(semanticModel, position), methodImplOptions.ToMinimalDisplayString(semanticModel, position));
aggressiveInliningAttribute = SyntaxHelpers.AggressiveInliningAttribute(
methodImplAttribute.ToMinimalDisplayString(semanticModel, position),
methodImplOptions.ToMinimalDisplayString(semanticModel, position), config.UseMethodImplNumeric);
}

public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
Expand Down
16 changes: 16 additions & 0 deletions Source/AtCoderAnalyzer/AtCoderAnalyzerConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using Microsoft.CodeAnalysis.Diagnostics;

namespace AtCoderAnalyzer
{
public record AtCoderAnalyzerConfig(bool UseMethodImplNumeric)
{
public static AtCoderAnalyzerConfig Parse(AnalyzerConfigOptions analyzerConfigOptions)
{
var useMethodImplNumeric = analyzerConfigOptions.TryGetValue("build_property.AtCoderAnalyzer_UseMethodImplNumeric", out var v) &&
StringComparer.OrdinalIgnoreCase.Equals(v, "true");

return new(useMethodImplNumeric);
}
}
}
54 changes: 27 additions & 27 deletions Source/AtCoderAnalyzer/CreateOperatorCodeFixProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
if (await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false)
is not CompilationUnitSyntax root)
return;
var config = AtCoderAnalyzerConfig.Parse(context.Document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GlobalOptions);
var diagnostic = context.Diagnostics[0];
var diagnosticSpan = diagnostic.Location.SourceSpan;

Expand Down Expand Up @@ -102,48 +103,47 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
}

var action = CodeAction.Create(title: title,
createChangedDocument: c => AddOperatorType(
createChangedDocument: c => new OperatorTypeSyntaxBuilder(semanticModel, config).AddOperatorType(
context.Document,
root,
semanticModel,
constraintArrayDic.ToImmutable()),
equivalenceKey: title);
context.RegisterCodeFix(action, diagnostic);
}

private async Task<Document> AddOperatorType(
Document document,
CompilationUnitSyntax root,
SemanticModel semanticModel,
ImmutableDictionary<string, ImmutableArray<ITypeSymbol>> constraintDic)
{
bool hasMethod = false;
var usings = root.Usings.ToNamespaceHashSet();
var builder = new OperatorTypeSyntaxBuilder(semanticModel);

MemberDeclarationSyntax[] newMembers = new MemberDeclarationSyntax[constraintDic.Count];
foreach (var (p, i) in constraintDic.Select((p, i) => (p, i)))
{
bool m;
(newMembers[i], m) = builder.Build(p.Key, p.Value);
hasMethod |= m;
}

root = root.AddMembers(newMembers);
return document.WithSyntaxRoot(root);
}

private class OperatorTypeSyntaxBuilder
{
private readonly SemanticModel semanticModel;
private readonly int origPosition;
public OperatorTypeSyntaxBuilder(SemanticModel semanticModel)
private AtCoderAnalyzerConfig config;
public OperatorTypeSyntaxBuilder(SemanticModel semanticModel, AtCoderAnalyzerConfig config)
{
this.semanticModel = semanticModel;
origPosition = semanticModel.SyntaxTree.Length;
this.config = config;
}

public async Task<Document> AddOperatorType(
Document document,
CompilationUnitSyntax root,
ImmutableDictionary<string, ImmutableArray<ITypeSymbol>> constraintDic)
{
bool hasMethod = false;
var usings = root.Usings.ToNamespaceHashSet();

MemberDeclarationSyntax[] newMembers = new MemberDeclarationSyntax[constraintDic.Count];
foreach (var (p, i) in constraintDic.Select((p, i) => (p, i)))
{
bool m;
(newMembers[i], m) = Build(p.Key, p.Value);
hasMethod |= m;
}

return document.WithSyntaxRoot(root.AddMembers(newMembers));

}

public (StructDeclarationSyntax syntax, bool hasMethod) Build(string operatorTypeName, ImmutableArray<ITypeSymbol> constraints)
private (StructDeclarationSyntax syntax, bool hasMethod) Build(string operatorTypeName, ImmutableArray<ITypeSymbol> constraints)
{
bool hasMethod = false;
var members = ImmutableList.CreateBuilder<MemberDeclarationSyntax>();
Expand All @@ -156,7 +156,7 @@ public OperatorTypeSyntaxBuilder(SemanticModel semanticModel)
if (!added.Add(baseType))
continue;

foreach (var (member, isMethod) in EnumerateMember.Create(semanticModel, baseType).EnumerateMemberSyntax())
foreach (var (member, isMethod) in EnumerateMember.Create(semanticModel, baseType, config).EnumerateMemberSyntax())
{
members.Add(member);
hasMethod |= isMethod;
Expand Down
31 changes: 17 additions & 14 deletions Source/AtCoderAnalyzer/CreateOperators/EnumerateMember.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,30 @@ internal class EnumerateMember
protected ITypeSymbol TypeSymbol { get; }
private readonly INamedTypeSymbol methodImplAttribute;
private readonly INamedTypeSymbol methodImplOptions;
protected EnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol)
private readonly AtCoderAnalyzerConfig config;
protected EnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol, AtCoderAnalyzerConfig config)
{
SemanticModel = semanticModel;
TypeSymbol = typeSymbol;
methodImplAttribute = semanticModel.Compilation.GetTypeByMetadataName(
Constants.System_Runtime_CompilerServices_MethodImplAttribute);
methodImplOptions = semanticModel.Compilation.GetTypeByMetadataName(
Constants.System_Runtime_CompilerServices_MethodImplOptions);
this.config = config;
}
public static EnumerateMember Create(SemanticModel semanticModel, ITypeSymbol typeSymbol) => typeSymbol.OriginalDefinition.ToDisplayString() switch
public static EnumerateMember Create(SemanticModel semanticModel, ITypeSymbol typeSymbol, AtCoderAnalyzerConfig config) => typeSymbol.OriginalDefinition.ToDisplayString() switch
{
"AtCoder.Operators.IAdditionOperator<T>" => new AdditionEnumerateMember(semanticModel, typeSymbol),
"AtCoder.Operators.ISubtractOperator<T>" => new SubtractEnumerateMember(semanticModel, typeSymbol),
"AtCoder.Operators.IMultiplicationOperator<T>" => new MultiplicationEnumerateMember(semanticModel, typeSymbol),
"AtCoder.Operators.IDivisionOperator<T>" => new DivisionEnumerateMember(semanticModel, typeSymbol),
"AtCoder.Operators.IUnaryNumOperator<T>" => new UnaryNumEnumerateMember(semanticModel, typeSymbol),
"AtCoder.Operators.ICompareOperator<T>" => new CompareOperatorEnumerateMember(semanticModel, typeSymbol),
"AtCoder.Operators.IMinMaxValue<T>" => new MinMaxValueEnumerateMember(semanticModel, typeSymbol),
"AtCoder.Operators.IShiftOperator<T>" => new ShiftEnumerateMember(semanticModel, typeSymbol),
"AtCoder.Operators.ICastOperator<TFrom, TTo>" => new CastEnumerateMember(semanticModel, typeSymbol),
"System.Collections.Generic.IComparer<T>" => new ComparerEnumerateMember(semanticModel, typeSymbol),
_ => new EnumerateMember(semanticModel, typeSymbol),
"AtCoder.Operators.IAdditionOperator<T>" => new AdditionEnumerateMember(semanticModel, typeSymbol, config),
"AtCoder.Operators.ISubtractOperator<T>" => new SubtractEnumerateMember(semanticModel, typeSymbol, config),
"AtCoder.Operators.IMultiplicationOperator<T>" => new MultiplicationEnumerateMember(semanticModel, typeSymbol, config),
"AtCoder.Operators.IDivisionOperator<T>" => new DivisionEnumerateMember(semanticModel, typeSymbol, config),
"AtCoder.Operators.IUnaryNumOperator<T>" => new UnaryNumEnumerateMember(semanticModel, typeSymbol, config),
"AtCoder.Operators.ICompareOperator<T>" => new CompareOperatorEnumerateMember(semanticModel, typeSymbol, config),
"AtCoder.Operators.IMinMaxValue<T>" => new MinMaxValueEnumerateMember(semanticModel, typeSymbol, config),
"AtCoder.Operators.IShiftOperator<T>" => new ShiftEnumerateMember(semanticModel, typeSymbol, config),
"AtCoder.Operators.ICastOperator<TFrom, TTo>" => new CastEnumerateMember(semanticModel, typeSymbol, config),
"System.Collections.Generic.IComparer<T>" => new ComparerEnumerateMember(semanticModel, typeSymbol, config),
_ => new EnumerateMember(semanticModel, typeSymbol, config),
};

public IEnumerable<(MemberDeclarationSyntax Syntax, bool IsMethod)> EnumerateMemberSyntax()
Expand Down Expand Up @@ -91,7 +93,8 @@ private MethodDeclarationSyntax CommonMethodDeclaration(IMethodSymbol symbol, Se
SingletonSeparatedList(
SyntaxHelpers.AggressiveInliningAttribute(
methodImplAttribute.ToMinimalDisplayString(semanticModel, position),
methodImplOptions.ToMinimalDisplayString(semanticModel, position))))))
methodImplOptions.ToMinimalDisplayString(semanticModel, position),
config.UseMethodImplNumeric)))))
.WithParameterList(symbol.ToParameterListSyntax(semanticModel, semanticModel.SyntaxTree.Length));
protected MethodDeclarationSyntax CreateMethodSyntax(SemanticModel semanticModel, int position, IMethodSymbol symbol, BlockSyntax block)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace AtCoderAnalyzer.CreateOperators
{
internal abstract class OperatorEnumerateMember : EnumerateMember
{
protected OperatorEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol) : base(semanticModel, typeSymbol) { }
protected OperatorEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol, AtCoderAnalyzerConfig config) : base(semanticModel, typeSymbol, config) { }
protected abstract SyntaxKind? GetSyntaxKind(IMethodSymbol symbol);

protected override MethodDeclarationSyntax CreateMethodSyntax(IMethodSymbol symbol)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AtCoderAnalyzer.CreateOperators.Specified
{
internal class AdditionEnumerateMember : OperatorEnumerateMember
{
internal AdditionEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol) : base(semanticModel, typeSymbol) { }
internal AdditionEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol, AtCoderAnalyzerConfig config) : base(semanticModel, typeSymbol, config) { }

protected override SyntaxKind? GetSyntaxKind(IMethodSymbol symbol)
=> symbol switch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace AtCoderAnalyzer.CreateOperators.Specified
{
internal class CastEnumerateMember : EnumerateMember
{
internal CastEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol) : base(semanticModel, typeSymbol) { }
internal CastEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol, AtCoderAnalyzerConfig config) : base(semanticModel, typeSymbol, config) { }
protected override MethodDeclarationSyntax CreateMethodSyntax(IMethodSymbol symbol)
{
if (symbol is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AtCoderAnalyzer.CreateOperators.Specified
{
internal class CompareOperatorEnumerateMember : OperatorEnumerateMember
{
internal CompareOperatorEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol) : base(semanticModel, typeSymbol) { }
internal CompareOperatorEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol, AtCoderAnalyzerConfig config) : base(semanticModel, typeSymbol, config) { }

protected override SyntaxKind? GetSyntaxKind(IMethodSymbol symbol)
=> symbol switch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace AtCoderAnalyzer.CreateOperators.Specified
{
internal class ComparerEnumerateMember : EnumerateMember
{
internal ComparerEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol) : base(semanticModel, typeSymbol) { }
internal ComparerEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol, AtCoderAnalyzerConfig config) : base(semanticModel, typeSymbol, config) { }
protected override MethodDeclarationSyntax CreateMethodSyntax(IMethodSymbol symbol)
{
if (symbol is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AtCoderAnalyzer.CreateOperators.Specified
{
internal class DivisionEnumerateMember : OperatorEnumerateMember
{
internal DivisionEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol) : base(semanticModel, typeSymbol) { }
internal DivisionEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol, AtCoderAnalyzerConfig config) : base(semanticModel, typeSymbol, config) { }

protected override SyntaxKind? GetSyntaxKind(IMethodSymbol symbol)
=> symbol switch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace AtCoderAnalyzer.CreateOperators.Specified
{
internal class MinMaxValueEnumerateMember : EnumerateMember
{
internal MinMaxValueEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol) : base(semanticModel, typeSymbol) { }
internal MinMaxValueEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol, AtCoderAnalyzerConfig config) : base(semanticModel, typeSymbol, config) { }
protected override PropertyDeclarationSyntax CreatePropertySyntax(IPropertySymbol symbol)
{
if (symbol is { Name: "MaxValue" or "MinValue" })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace AtCoderAnalyzer.CreateOperators.Specified
{
internal class MultiplicationEnumerateMember : OperatorEnumerateMember
{
internal MultiplicationEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol) : base(semanticModel, typeSymbol) { }
internal MultiplicationEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol, AtCoderAnalyzerConfig config) : base(semanticModel, typeSymbol, config) { }

protected override SyntaxKind? GetSyntaxKind(IMethodSymbol symbol)
=> symbol switch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AtCoderAnalyzer.CreateOperators.Specified
{
internal class ShiftEnumerateMember : OperatorEnumerateMember
{
internal ShiftEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol) : base(semanticModel, typeSymbol) { }
internal ShiftEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol, AtCoderAnalyzerConfig config) : base(semanticModel, typeSymbol, config) { }
protected override SyntaxKind? GetSyntaxKind(IMethodSymbol symbol)
=> symbol switch
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace AtCoderAnalyzer.CreateOperators.Specified
{
internal class SubtractEnumerateMember : OperatorEnumerateMember
{
internal SubtractEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol) : base(semanticModel, typeSymbol) { }
internal SubtractEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol, AtCoderAnalyzerConfig config) : base(semanticModel, typeSymbol, config) { }

protected override SyntaxKind? GetSyntaxKind(IMethodSymbol symbol)
=> symbol switch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace AtCoderAnalyzer.CreateOperators.Specified
{
internal class UnaryNumEnumerateMember : EnumerateMember
{
internal UnaryNumEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol) : base(semanticModel, typeSymbol) { }
internal UnaryNumEnumerateMember(SemanticModel semanticModel, ITypeSymbol typeSymbol, AtCoderAnalyzerConfig config) : base(semanticModel, typeSymbol, config) { }

protected override MethodDeclarationSyntax CreateMethodSyntax(IMethodSymbol symbol)
{
Expand Down
Loading

0 comments on commit 7f58c8a

Please sign in to comment.