From 8816842e140cf2fe6fa1784c3cdf019010cc7567 Mon Sep 17 00:00:00 2001 From: Arthur van de Vondervoort Date: Sat, 6 Jul 2024 20:42:52 +0200 Subject: [PATCH 1/2] Add Rule0064 Use table field ToolTip instead of page field ToolTip --- ...leFieldToolTipInsteadOfPageFieldToolTip.cs | 63 +++++++++++++++++++ .../LinterCop.ruleset.json | 5 ++ .../LinterCopAnalyzers.Generated.cs | 1 + .../LinterCopAnalyzers.resx | 9 +++ README.md | 3 +- 5 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 BusinessCentral.LinterCop/Design/Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip.cs diff --git a/BusinessCentral.LinterCop/Design/Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip.cs b/BusinessCentral.LinterCop/Design/Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip.cs new file mode 100644 index 00000000..9f170cbf --- /dev/null +++ b/BusinessCentral.LinterCop/Design/Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip.cs @@ -0,0 +1,63 @@ +using BusinessCentral.LinterCop.AnalysisContextExtension; +using Microsoft.Dynamics.Nav.CodeAnalysis; +using Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics; +using System.Collections.Immutable; + +namespace BusinessCentral.LinterCop.Design +{ + [DiagnosticAnalyzer] + public class Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip : DiagnosticAnalyzer + { + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagnosticDescriptors.Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip); + + public override void Initialize(AnalysisContext context) => context.RegisterSymbolAction(new Action(this.AnalyzeFlowFieldEditable), SymbolKind.Page, SymbolKind.PageExtension); + + private void AnalyzeFlowFieldEditable(SymbolAnalysisContext ctx) + { + if (!VersionChecker.IsSupported(ctx.Symbol, VersionCompatibility.Spring2024OrGreater)) return; + + if (ctx.IsObsoletePendingOrRemoved()) return; + + IEnumerable pageFields = GetFlattenedControls(ctx.Symbol) + .Where(e => e.ControlKind == ControlKind.Field) + .Where(e => e.GetProperty(PropertyKind.ToolTip) != null) + .Where(e => e.RelatedFieldSymbol != null); + if (pageFields == null) return; + + foreach (IControlSymbol page in pageFields) + { + ctx.CancellationToken.ThrowIfCancellationRequested(); + + IPropertySymbol pageToolTip = page.GetProperty(PropertyKind.ToolTip); + IPropertySymbol tableToolTip = page.RelatedFieldSymbol.GetProperty(PropertyKind.ToolTip); + + // Page field has a value for the ToolTip property and table field does not have a value for the ToolTip property + if (tableToolTip == null && page.RelatedFieldSymbol.IsSourceSymbol()) + { + ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip, pageToolTip.GetLocation())); + continue; + } + + // Page field has a value for the ToolTip property and table field also has a value for the ToolTip property but the value is exactly the same + if (tableToolTip != null && pageToolTip.ValueText == tableToolTip.ValueText) + { + ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip, pageToolTip.GetLocation())); + continue; + } + } + } + + private static IEnumerable GetFlattenedControls(ISymbol symbol) + { + switch (symbol.Kind) + { + case SymbolKind.Page: + return ((IPageBaseTypeSymbol)symbol).FlattenedControls; + case SymbolKind.PageExtension: + return ((IPageExtensionBaseTypeSymbol)symbol).AddedControlsFlattened; + default: + return null; + } + } + } +} diff --git a/BusinessCentral.LinterCop/LinterCop.ruleset.json b/BusinessCentral.LinterCop/LinterCop.ruleset.json index e4edd08e..f9d95ae2 100644 --- a/BusinessCentral.LinterCop/LinterCop.ruleset.json +++ b/BusinessCentral.LinterCop/LinterCop.ruleset.json @@ -316,6 +316,11 @@ "id": "LC0063", "action": "Info", "justification": "Consider naming field with a more descriptive name." + }, + { + "id": "LC0064", + "action": "Info", + "justification": "Use table field ToolTip instead of page field ToolTip." } ] } \ No newline at end of file diff --git a/BusinessCentral.LinterCop/LinterCopAnalyzers.Generated.cs b/BusinessCentral.LinterCop/LinterCopAnalyzers.Generated.cs index b6a33d17..ae050449 100644 --- a/BusinessCentral.LinterCop/LinterCopAnalyzers.Generated.cs +++ b/BusinessCentral.LinterCop/LinterCopAnalyzers.Generated.cs @@ -70,5 +70,6 @@ public static class DiagnosticDescriptors public static readonly DiagnosticDescriptor Rule0061SetODataKeyFieldsWithSystemIdField = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0061", (LocalizableString)new LocalizableResourceString("Rule0061SetODataKeyFieldsWithSystemIdFieldTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0061SetODataKeyFieldsWithSystemIdFieldFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0061SetODataKeyFieldsWithSystemIdFieldDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0061"); public static readonly DiagnosticDescriptor Rule0062MandatoryFieldMissingOnApiPage = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0062", (LocalizableString)new LocalizableResourceString("Rule0062MandatoryFieldMissingOnApiPageTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0062MandatoryFieldMissingOnApiPageFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0062MandatoryFieldMissingOnApiPageDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0062"); public static readonly DiagnosticDescriptor Rule0063GiveFieldMoreDescriptiveName = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0063", (LocalizableString)new LocalizableResourceString("Rule0063GiveFieldMoreDescriptiveNameTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0063GiveFieldMoreDescriptiveNameFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0063GiveFieldMoreDescriptiveNameDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0063"); + public static readonly DiagnosticDescriptor Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0064", (LocalizableString)new LocalizableResourceString("Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTipTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTipFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTipDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0064"); } } \ No newline at end of file diff --git a/BusinessCentral.LinterCop/LinterCopAnalyzers.resx b/BusinessCentral.LinterCop/LinterCopAnalyzers.resx index 752425e7..2ed6aa3d 100644 --- a/BusinessCentral.LinterCop/LinterCopAnalyzers.resx +++ b/BusinessCentral.LinterCop/LinterCopAnalyzers.resx @@ -681,4 +681,13 @@ Consider naming field with a more descriptive name: '{0}'. + + Use table field ToolTip instead of page field ToolTip. + + + Use table field ToolTip instead of page field ToolTip. + + + Use table field ToolTip instead of page field ToolTip. + \ No newline at end of file diff --git a/README.md b/README.md index 8b5beb7a..e8ed2bd8 100644 --- a/README.md +++ b/README.md @@ -216,4 +216,5 @@ For an example and the default values see: [LinterCop.ruleset.json](LinterCop.ru |[LC0060](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0060)|The `ApplicationArea` property is not applicable to API pages.|Info| |[LC0061](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0061)|Pages of type API must have the `ODataKeyFields` property set to the SystemId field.|Info| |[LC0062](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0062)|Mandatory field is missing on API page.|Info| -|[LC0063](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0063)|Consider naming field with a more descriptive name.|Info| \ No newline at end of file +|[LC0063](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0063)|Consider naming field with a more descriptive name.|Info| +|[LC0064](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0064)|Use table field ToolTip instead of page field ToolTip.|Info| \ No newline at end of file From db52ce1b9a9549142b6a35cff868aea8851849b9 Mon Sep 17 00:00:00 2001 From: Arthur van de Vondervoort Date: Sat, 6 Jul 2024 20:50:08 +0200 Subject: [PATCH 2/2] Add preprocessor directive --- .../Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/BusinessCentral.LinterCop/Design/Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip.cs b/BusinessCentral.LinterCop/Design/Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip.cs index 9f170cbf..efacdaaa 100644 --- a/BusinessCentral.LinterCop/Design/Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip.cs +++ b/BusinessCentral.LinterCop/Design/Rule0064UseTableFieldToolTipInsteadOfPageFieldToolTip.cs @@ -1,3 +1,4 @@ +#if Spring2024OrGreater using BusinessCentral.LinterCop.AnalysisContextExtension; using Microsoft.Dynamics.Nav.CodeAnalysis; using Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics; @@ -61,3 +62,4 @@ private static IEnumerable GetFlattenedControls(ISymbol symbol) } } } +#endif \ No newline at end of file