Skip to content

Commit

Permalink
Investigate exception (#823)
Browse files Browse the repository at this point in the history
  • Loading branch information
Arthurvdv authored Dec 5, 2024
1 parent c8534f3 commit 70fa66a
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,48 @@ public class Rule0051SetFilterPossibleOverflow : DiagnosticAnalyzer
{
private readonly Lazy<Regex> strSubstNoPatternLazy = new Lazy<Regex>((Func<Regex>)(() => new Regex("[#%](\\d+)", RegexOptions.Compiled)));

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create<DiagnosticDescriptor>(DiagnosticDescriptors.Rule0051SetFilterPossibleOverflow);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create<DiagnosticDescriptor>(DiagnosticDescriptors.Rule0051SetFilterPossibleOverflow, DiagnosticDescriptors.Rule0000ErrorInRule);

private Regex StrSubstNoPattern => this.strSubstNoPatternLazy.Value;

public override void Initialize(AnalysisContext context) => context.RegisterOperationAction(new Action<OperationAnalysisContext>(this.AnalyzeInvocation), OperationKind.InvocationExpression);

private void AnalyzeInvocation(OperationAnalysisContext ctx)
{
if (ctx.IsObsoletePendingOrRemoved()) return;
// Investigate https://github.com/StefanMaron/BusinessCentral.LinterCop/issues/822
try
{
if (ctx.IsObsoletePendingOrRemoved()) return;

IInvocationExpression operation = (IInvocationExpression)ctx.Operation;
if (operation.TargetMethod.MethodKind != MethodKind.BuiltInMethod) return;
IInvocationExpression operation = (IInvocationExpression)ctx.Operation;
if (operation.TargetMethod.MethodKind != MethodKind.BuiltInMethod) return;

if (operation.TargetMethod == null || !SemanticFacts.IsSameName(operation.TargetMethod.Name, "SetFilter") || operation.Arguments.Count() < 3)
return;
if (operation.TargetMethod == null || !SemanticFacts.IsSameName(operation.TargetMethod.Name, "SetFilter") || operation.Arguments.Count() < 3)
return;

if (operation.Arguments[0].Value.Kind != OperationKind.ConversionExpression) return;
IOperation fieldOperand = ((IConversionExpression)operation.Arguments[0].Value).Operand;
ITypeSymbol fieldType = fieldOperand.Type;
if (fieldType.GetNavTypeKindSafe() == NavTypeKind.Text) return;
if (operation.Arguments[0].Value.Kind != OperationKind.ConversionExpression) return;
IOperation fieldOperand = ((IConversionExpression)operation.Arguments[0].Value).Operand;
ITypeSymbol fieldType = fieldOperand.Type;
if (fieldType.GetNavTypeKindSafe() == NavTypeKind.Text) return;

bool isError = false;
int typeLength = GetTypeLength(fieldType, ref isError);
if (isError || typeLength == int.MaxValue)
return;
bool isError = false;
int typeLength = GetTypeLength(fieldType, ref isError);
if (isError || typeLength == int.MaxValue)
return;

foreach (int argIndex in GetArgumentIndexes(operation.Arguments[1].Value))
{
int index = argIndex + 1; // The placeholders are defines as %1, %2, %3, where in case of %1 we need the second (zero based) index of the arguments of the SetFilter method
if (index < 2 || index >= operation.Arguments.Count()) continue;
foreach (int argIndex in GetArgumentIndexes(operation.Arguments[1].Value))
{
int index = argIndex + 1; // The placeholders are defines as %1, %2, %3, where in case of %1 we need the second (zero based) index of the arguments of the SetFilter method
if (index < 2 || index >= operation.Arguments.Count()) continue;

int expressionLength = this.CalculateMaxExpressionLength(((IConversionExpression)operation.Arguments[index].Value).Operand, ref isError);
if (!isError && expressionLength > typeLength)
ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0051SetFilterPossibleOverflow, operation.Syntax.GetLocation(), GetDisplayString(operation.Arguments[index], operation), GetDisplayString(operation.Arguments[0], operation)));
int expressionLength = this.CalculateMaxExpressionLength(((IConversionExpression)operation.Arguments[index].Value).Operand, ref isError);
if (!isError && expressionLength > typeLength)
ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0051SetFilterPossibleOverflow, operation.Syntax.GetLocation(), GetDisplayString(operation.Arguments[index], operation), GetDisplayString(operation.Arguments[0], operation)));
}
}
catch (InvalidCastException)
{
ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0000ErrorInRule, ctx.Operation.Syntax.GetLocation(), new Object[] { "Rule0051", "InvalidCastException", "" }));
}
}

Expand Down
60 changes: 34 additions & 26 deletions BusinessCentral.LinterCop/Design/Rule0059SingleQuoteEscaping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace BusinessCentral.LinterCop.Design
[DiagnosticAnalyzer]
public class Rule0059SingleQuoteEscaping : DiagnosticAnalyzer
{
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create<DiagnosticDescriptor>(DiagnosticDescriptors.Rule0050OperatorAndPlaceholderInFilterExpression, DiagnosticDescriptors.Rule0059SingleQuoteEscapingIssueDetected);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create<DiagnosticDescriptor>(DiagnosticDescriptors.Rule0050OperatorAndPlaceholderInFilterExpression, DiagnosticDescriptors.Rule0059SingleQuoteEscapingIssueDetected, DiagnosticDescriptors.Rule0000ErrorInRule);

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

Expand All @@ -18,39 +18,47 @@ public override void Initialize(AnalysisContext context) =>

private void AnalyzeCalcFormula(SymbolAnalysisContext ctx)
{
if (ctx.IsObsoletePendingOrRemoved())
return;
// Investigate https://github.com/StefanMaron/BusinessCentral.LinterCop/issues/822
try
{
if (ctx.IsObsoletePendingOrRemoved())
return;

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

if (syntaxNode is not FieldSyntax fieldSyntax)
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<CalculationFormulaPropertyValueSyntax>()
.FirstOrDefault();
// Retrieve the 'CalcFormula' property from the field's property list
var calcFormulaPropertySyntax = fieldSyntax.PropertyList?.Properties
.OfType<PropertySyntax>()
.Select(p => p.Value)
.OfType<CalculationFormulaPropertyValueSyntax>()
.FirstOrDefault();

if (calcFormulaPropertySyntax is null)
return;
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);
// 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;
if (filterExpressions is null)
return;

foreach (var filter in filterExpressions)
foreach (var filter in filterExpressions)
{
if (filter.ToString().Equals(InvalidUnaryEqualsFilter))
ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0059SingleQuoteEscapingIssueDetected, filter.GetLocation()));
}
}
catch (NullReferenceException)
{
if (filter.ToString().Equals(InvalidUnaryEqualsFilter))
ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0059SingleQuoteEscapingIssueDetected, filter.GetLocation()));
ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0000ErrorInRule, ctx.Symbol.GetLocation(), new Object[] { "Rule0029", "NullReferenceException", "" }));
}
}
}
Expand Down

0 comments on commit 70fa66a

Please sign in to comment.