diff --git a/Design/Rule0039PageRunTableMismatch.cs b/Design/Rule0039PageRunTableMismatch.cs new file mode 100644 index 00000000..0d8ab00d --- /dev/null +++ b/Design/Rule0039PageRunTableMismatch.cs @@ -0,0 +1,42 @@ +using Microsoft.Dynamics.Nav.CodeAnalysis; +using Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics; +using Microsoft.Dynamics.Nav.CodeAnalysis.Symbols; +using Microsoft.Dynamics.Nav.CodeAnalysis.Syntax; +using System.Collections.Immutable; + +namespace BusinessCentral.LinterCop.Design +{ + [DiagnosticAnalyzer] + public class Rule0039PageRunTableMismatch : DiagnosticAnalyzer + { + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagnosticDescriptors.Rule0039ArgumentDifferentTypeThenExpected); + + public override void Initialize(AnalysisContext context) => context.RegisterOperationAction(new Action(this.AnalyzeRunPageArguments), OperationKind.InvocationExpression); + + private void AnalyzeRunPageArguments(OperationAnalysisContext ctx) + { + if (ctx.ContainingSymbol.GetContainingObjectTypeSymbol().IsObsoletePending || ctx.ContainingSymbol.GetContainingObjectTypeSymbol().IsObsoleteRemoved) return; + if (ctx.ContainingSymbol.IsObsoletePending || ctx.ContainingSymbol.IsObsoleteRemoved) return; + + IInvocationExpression operation = (IInvocationExpression)ctx.Operation; + if (operation.TargetMethod.MethodKind != MethodKind.BuiltInMethod) return; + + if (operation.TargetMethod.ContainingType.GetTypeSymbol().GetNavTypeKindSafe() != NavTypeKind.Page) return; + if (operation.Arguments.Count() < 2) return; + + if (operation.Arguments[0].Syntax.Kind != SyntaxKind.OptionAccessExpression) return; + if (operation.Arguments[1].Syntax.Kind != SyntaxKind.IdentifierName) return; + + IApplicationObjectTypeSymbol applicationObjectTypeSymbol = ((IApplicationObjectAccess)operation.Arguments[0].Value).ApplicationObjectTypeSymbol; + if (applicationObjectTypeSymbol.GetNavTypeKindSafe() != NavTypeKind.Page) return; + ITableTypeSymbol pageObjSourceTable = ((IPageTypeSymbol)applicationObjectTypeSymbol.GetTypeSymbol()).RelatedTable; + if (pageObjSourceTable == null) return; + + IOperation operand = ((IConversionExpression)operation.Arguments[1].Value).Operand; + ITableTypeSymbol recordArgument = ((IRecordTypeSymbol)operand.GetSymbol().GetTypeSymbol()).BaseTable; + + if (recordArgument != pageObjSourceTable) + ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0039ArgumentDifferentTypeThenExpected, ctx.Operation.Syntax.GetLocation(), new object[] { 2, operand.GetSymbol().GetTypeSymbol().ToString(), "Record \"" + pageObjSourceTable.Name + "\"" })); + } + } +} \ No newline at end of file diff --git a/LinterCop.ruleset.json b/LinterCop.ruleset.json index b7f1f6b6..c63181d6 100644 --- a/LinterCop.ruleset.json +++ b/LinterCop.ruleset.json @@ -191,6 +191,11 @@ "id": "LC0038", "action": "Info", "justification": "Try to not exceed 200 characters (including spaces)." + }, + { + "id": "LC0039", + "action": "Warning", + "justification": "The given argument has a different type from the one expected." } ] } \ No newline at end of file diff --git a/LinterCopAnalyzers.Generated.cs b/LinterCopAnalyzers.Generated.cs index dfa6588d..997c842f 100644 --- a/LinterCopAnalyzers.Generated.cs +++ b/LinterCopAnalyzers.Generated.cs @@ -45,5 +45,6 @@ public static class DiagnosticDescriptors public static readonly DiagnosticDescriptor Rule0036ToolTipShouldStartWithSpecifies = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0036", (LocalizableString)new LocalizableResourceString("Rule0036ToolTipShouldStartWithSpecifiesTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0036ToolTipShouldStartWithSpecifiesFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0036ToolTipShouldStartWithSpecifiesDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0036"); public static readonly DiagnosticDescriptor Rule0037ToolTipDoNotUseLineBreaks = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0037", (LocalizableString)new LocalizableResourceString("Rule0037ToolTipDoNotUseLineBreaksTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0037ToolTipDoNotUseLineBreaksFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0037ToolTipDoNotUseLineBreaksDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0037"); public static readonly DiagnosticDescriptor Rule0038ToolTipMaximumLength = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0038", (LocalizableString)new LocalizableResourceString("Rule0038ToolTipMaximumLengthTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0038ToolTipMaximumLengthFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0038ToolTipMaximumLengthDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0038"); + public static readonly DiagnosticDescriptor Rule0039ArgumentDifferentTypeThenExpected = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0039", (LocalizableString)new LocalizableResourceString("Rule0039ArgumentDifferentTypeThenExpectedTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0039ArgumentDifferentTypeThenExpectedFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Warning, true, (LocalizableString)new LocalizableResourceString("Rule0039ArgumentDifferentTypeThenExpectedDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0039"); } } \ No newline at end of file diff --git a/LinterCopAnalyzers.resx b/LinterCopAnalyzers.resx index 2263c04c..989e26a7 100644 --- a/LinterCopAnalyzers.resx +++ b/LinterCopAnalyzers.resx @@ -447,4 +447,13 @@ Try to not exceed 200 characters (including spaces). + + Argument {0}: cannot convert from '{1}' to '{2}'. + + + Argument {0}: cannot convert from '{1}' to '{2}'. + + + Argument {0}: cannot convert from '{1}' to '{2}'. + \ No newline at end of file diff --git a/README.md b/README.md index 3f38db5f..6e42b015 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ Further note that you should have BcContainerHelper version 2.0.16 (or newer) in |[LC0036](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0036)|For fields specifically, the ToolTip must start with the verb Specifies.|Info| |[LC0037](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0037)|Do not use line breaks in ToolTip.|Info| |[LC0038](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0038)|Try to not exceed 200 characters (including spaces).|Info| +|[LC0039](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0039)|The given argument has a different type from the one expected.|Warning| ## Configuration