Skip to content

Commit

Permalink
Extend Rule0059 to where filter expression on CalcFormula property (#817
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Arthurvdv authored Nov 26, 2024
1 parent ceb82bf commit 4efa606
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 0 deletions.
35 changes: 35 additions & 0 deletions BusinessCentral.LinterCop.Test/Rule0059.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace BusinessCentral.LinterCop.Test;

public class Rule0059
{
private string _testCaseDir = "";

[SetUp]
public void Setup()
{
_testCaseDir = Path.Combine(Directory.GetParent(Environment.CurrentDirectory)!.Parent!.Parent!.FullName,
"TestCases", "Rule0059");
}

[Test]
[TestCase("CalcFormulaWhere")]
public async Task HasDiagnostic(string testCase)
{
var code = await File.ReadAllTextAsync(Path.Combine(_testCaseDir, "HasDiagnostic", $"{testCase}.al"))
.ConfigureAwait(false);

var fixture = RoslynFixtureFactory.Create<Rule0059SingleQuoteEscaping>();
fixture.HasDiagnostic(code, DiagnosticDescriptors.Rule0059SingleQuoteEscapingIssueDetected.Id);
}

[Test]
[TestCase("CalcFormulaWhere")]
public async Task NoDiagnostic(string testCase)
{
var code = await File.ReadAllTextAsync(Path.Combine(_testCaseDir, "NoDiagnostic", $"{testCase}.al"))
.ConfigureAwait(false);

var fixture = RoslynFixtureFactory.Create<Rule0059SingleQuoteEscaping>();
fixture.NoDiagnosticAtMarker(code, DiagnosticDescriptors.Rule0059SingleQuoteEscapingIssueDetected.Id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
table 50100 MyTable
{
fields
{
field(1; MyField; Integer) { }
field(2; MyFlowField; Integer)
{
FieldClass = FlowField;
CalcFormula = count(MyTable where(MyField = filter([|'<>'''|])));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
table 50100 MyTable
{
fields
{
field(1; MyField; Integer) { }
field(2; MyFlowField; Integer)
{
FieldClass = FlowField;
CalcFormula = count(MyTable where(MyField = filter([|'<>'''''|])));
}
}
}
57 changes: 57 additions & 0 deletions BusinessCentral.LinterCop/Design/Rule0059SingleQuoteEscaping.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using BusinessCentral.LinterCop.AnalysisContextExtension;
using Microsoft.Dynamics.Nav.CodeAnalysis;
using Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics;
using Microsoft.Dynamics.Nav.CodeAnalysis.Syntax;
using System.Collections.Immutable;

namespace BusinessCentral.LinterCop.Design
{
[DiagnosticAnalyzer]
public class Rule0059SingleQuoteEscaping : DiagnosticAnalyzer
{
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create<DiagnosticDescriptor>(DiagnosticDescriptors.Rule0050OperatorAndPlaceholderInFilterExpression, DiagnosticDescriptors.Rule0059SingleQuoteEscapingIssueDetected);

private static readonly string InvalidUnaryEqualsFilter = "'<>'''";

public override void Initialize(AnalysisContext context) =>
context.RegisterSymbolAction(new Action<SymbolAnalysisContext>(this.AnalyzeCalcFormula), SymbolKind.Field);

private void AnalyzeCalcFormula(SymbolAnalysisContext ctx)
{
if (ctx.IsObsoletePendingOrRemoved())
return;

SyntaxNode? syntaxNode = ctx.Symbol.DeclaringSyntaxReference?.GetSyntax(ctx.CancellationToken);
if (syntaxNode == null)
return;

if (syntaxNode is not FieldSyntax fieldSyntax)
return;

// Retrieve the 'CalcFormula' property from the field's property list
var calcFormulaPropertySyntax = fieldSyntax.PropertyList?.Properties
.OfType<PropertySyntax>()
.Select(p => p.Value)
.OfType<TableCalculationFormulaSyntax>()
.FirstOrDefault();

if (calcFormulaPropertySyntax is null)
return;

// Retrieve the filter expression from the 'Where' expression of the CalcFormula
var filterExpressions = calcFormulaPropertySyntax.WhereExpression.Filter.Conditions
.OfType<FilterExpressionSyntax>()
.Where(c => c.Filter.Kind == SyntaxKind.UnaryEqualsFilterExpression)
.Select(c => c.Filter);

if (filterExpressions is null)
return;

foreach (var filter in filterExpressions)
{
if (filter.ToString().Equals(InvalidUnaryEqualsFilter))
ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0059SingleQuoteEscapingIssueDetected, filter.GetLocation()));
}
}
}
}

0 comments on commit 4efa606

Please sign in to comment.