From 70fa66a646e9fab15d7b3843f942ae9629be658e Mon Sep 17 00:00:00 2001 From: Arthur van de Vondervoort <44637996+Arthurvdv@users.noreply.github.com> Date: Thu, 5 Dec 2024 19:47:21 +0100 Subject: [PATCH] Investigate exception (#823) --- .../Rule0051SetFilterPossibleOverflow.cs | 50 +++++++++------- .../Design/Rule0059SingleQuoteEscaping.cs | 60 +++++++++++-------- 2 files changed, 63 insertions(+), 47 deletions(-) diff --git a/BusinessCentral.LinterCop/Design/Rule0051SetFilterPossibleOverflow.cs b/BusinessCentral.LinterCop/Design/Rule0051SetFilterPossibleOverflow.cs index 5804c01..92f5e0d 100644 --- a/BusinessCentral.LinterCop/Design/Rule0051SetFilterPossibleOverflow.cs +++ b/BusinessCentral.LinterCop/Design/Rule0051SetFilterPossibleOverflow.cs @@ -14,7 +14,7 @@ public class Rule0051SetFilterPossibleOverflow : DiagnosticAnalyzer { private readonly Lazy strSubstNoPatternLazy = new Lazy((Func)(() => new Regex("[#%](\\d+)", RegexOptions.Compiled))); - public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagnosticDescriptors.Rule0051SetFilterPossibleOverflow); + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagnosticDescriptors.Rule0051SetFilterPossibleOverflow, DiagnosticDescriptors.Rule0000ErrorInRule); private Regex StrSubstNoPattern => this.strSubstNoPatternLazy.Value; @@ -22,32 +22,40 @@ public class Rule0051SetFilterPossibleOverflow : DiagnosticAnalyzer 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", "" })); } } diff --git a/BusinessCentral.LinterCop/Design/Rule0059SingleQuoteEscaping.cs b/BusinessCentral.LinterCop/Design/Rule0059SingleQuoteEscaping.cs index 4947c74..008d1b3 100644 --- a/BusinessCentral.LinterCop/Design/Rule0059SingleQuoteEscaping.cs +++ b/BusinessCentral.LinterCop/Design/Rule0059SingleQuoteEscaping.cs @@ -9,7 +9,7 @@ namespace BusinessCentral.LinterCop.Design [DiagnosticAnalyzer] public class Rule0059SingleQuoteEscaping : DiagnosticAnalyzer { - public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagnosticDescriptors.Rule0050OperatorAndPlaceholderInFilterExpression, DiagnosticDescriptors.Rule0059SingleQuoteEscapingIssueDetected); + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagnosticDescriptors.Rule0050OperatorAndPlaceholderInFilterExpression, DiagnosticDescriptors.Rule0059SingleQuoteEscapingIssueDetected, DiagnosticDescriptors.Rule0000ErrorInRule); private static readonly string InvalidUnaryEqualsFilter = "'<>'''"; @@ -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() - .Select(p => p.Value) - .OfType() - .FirstOrDefault(); + // Retrieve the 'CalcFormula' property from the field's property list + var calcFormulaPropertySyntax = fieldSyntax.PropertyList?.Properties + .OfType() + .Select(p => p.Value) + .OfType() + .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() - .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() + .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", "" })); } } }