From ff5ae20bede9bc6ba7251fa3f207fc24dbc709f2 Mon Sep 17 00:00:00 2001 From: Arthur van de Vondervoort Date: Tue, 21 Nov 2023 14:44:37 +0100 Subject: [PATCH] New rule LC0034 Set explicit Extensible property --- ...0034ExtensiblePropertyShouldAlwaysBeSet.cs | 36 +++++++++++++++++++ LinterCop.ruleset.json | 5 +++ LinterCopAnalyzers.Generated.cs | 1 + LinterCopAnalyzers.resx | 9 +++++ README.md | 1 + 5 files changed, 52 insertions(+) create mode 100644 Design/Rule0034ExtensiblePropertyShouldAlwaysBeSet.cs diff --git a/Design/Rule0034ExtensiblePropertyShouldAlwaysBeSet.cs b/Design/Rule0034ExtensiblePropertyShouldAlwaysBeSet.cs new file mode 100644 index 00000000..f0baf03b --- /dev/null +++ b/Design/Rule0034ExtensiblePropertyShouldAlwaysBeSet.cs @@ -0,0 +1,36 @@ +using Microsoft.Dynamics.Nav.Analyzers.Common.AppSourceCopConfiguration; +using Microsoft.Dynamics.Nav.CodeAnalysis; +using Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics; +using Microsoft.Dynamics.Nav.CodeAnalysis.Symbols; +using System.Collections.Immutable; + +namespace BusinessCentral.LinterCop.Design +{ + [DiagnosticAnalyzer] + public class Rule0034ExtensiblePropertyShouldAlwaysBeSet : DiagnosticAnalyzer + { + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagnosticDescriptors.Rule0034ExtensiblePropertyShouldAlwaysBeSet); + + public override void Initialize(AnalysisContext context) + => context.RegisterSymbolAction(new Action(this.CheckForMissingExtensibleProperty), new SymbolKind[] { + SymbolKind.Table, + SymbolKind.Page, + SymbolKind.Report + }); + + private void CheckForMissingExtensibleProperty(SymbolAnalysisContext ctx) + { + // The Extensible property (and DeclaredAccessibility) is supported from runtime versions 4.0 or greater. + var manifest = AppSourceCopConfigurationProvider.GetManifest(ctx.Compilation); + if (manifest.Runtime < RuntimeVersion.Fall2019) return; + + if (ctx.Symbol.IsObsoletePending || ctx.Symbol.IsObsoleteRemoved) return; + + if (ctx.Symbol.GetTypeSymbol().Kind == SymbolKind.Table && ctx.Symbol.DeclaredAccessibility != Accessibility.Public) return; + if (ctx.Symbol.GetTypeSymbol().Kind == SymbolKind.Page && ((IPageTypeSymbol)ctx.Symbol.GetTypeSymbol()).PageType == PageTypeKind.API) return; + + if (ctx.Symbol.GetProperty(PropertyKind.Extensible) is null) + ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0034ExtensiblePropertyShouldAlwaysBeSet, ctx.Symbol.GetLocation(), new object[] { Accessibility.Public.ToString().ToLower() })); + } + } +} \ No newline at end of file diff --git a/LinterCop.ruleset.json b/LinterCop.ruleset.json index 8177407e..27b1e8ab 100644 --- a/LinterCop.ruleset.json +++ b/LinterCop.ruleset.json @@ -166,6 +166,11 @@ "id": "LC0033", "action": "Info", "justification": "The specified runtime version in app.json is falling behind." + }, + { + "id": "LC0034", + "action": "Hidden", + "justification": "The property Extensible should be explicitly set for public objects." } ] } \ No newline at end of file diff --git a/LinterCopAnalyzers.Generated.cs b/LinterCopAnalyzers.Generated.cs index 47b5ce65..aa8f7434 100644 --- a/LinterCopAnalyzers.Generated.cs +++ b/LinterCopAnalyzers.Generated.cs @@ -40,5 +40,6 @@ public static class DiagnosticDescriptors public static readonly DiagnosticDescriptor Rule0031RecordInstanceIsolationLevel = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0031", (LocalizableString)new LocalizableResourceString("Rule0031RecordInstanceIsolationLevelTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0031RecordInstanceIsolationLevelFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0031RecordInstanceIsolationLevelDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0031"); public static readonly DiagnosticDescriptor Rule0032ClearCodeunitSingleInstance = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0032", (LocalizableString)new LocalizableResourceString("Rule0032ClearCodeunitSingleInstanceTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0032ClearCodeunitSingleInstanceFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Warning, true, (LocalizableString)new LocalizableResourceString("Rule0032ClearCodeunitSingleInstanceDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0032"); public static readonly DiagnosticDescriptor Rule0033AppManifestRuntimeBehind = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0033", (LocalizableString)new LocalizableResourceString("Rule0033AppManifestRuntimeBehindTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0033AppManifestRuntimeBehindFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0033AppManifestRuntimeBehindTitleDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0033"); + public static readonly DiagnosticDescriptor Rule0034ExtensiblePropertyShouldAlwaysBeSet = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0034", (LocalizableString)new LocalizableResourceString("Rule0034ExtensiblePropertyShouldAlwaysBeSetTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0034ExtensiblePropertyShouldAlwaysBeSetFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Hidden, true, (LocalizableString)new LocalizableResourceString("Rule0034ExtensiblePropertyShouldAlwaysBeSetDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0034"); } } \ No newline at end of file diff --git a/LinterCopAnalyzers.resx b/LinterCopAnalyzers.resx index 172e6172..23f11e1f 100644 --- a/LinterCopAnalyzers.resx +++ b/LinterCopAnalyzers.resx @@ -402,4 +402,13 @@ The specified runtime version in app.json is falling behind. The project targets {0} version {1}, but the current runtime is {2}. Update the runtime to {3} for compatibility with the latest runtime features. + + The property Extensible should be explicitly set for {0} objects. + + + The property Extensible should be explicitly set for {0} objects. + + + The property Extensible should be explicitly set for {0} objects. + \ No newline at end of file diff --git a/README.md b/README.md index f2fe96d7..8b9e48e7 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ Further note that you should have BcContainerHelper version 2.0.16 (or newer) in |[LC0031](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0031)|Set ReadIsolation property instead of LockTable method.|Info| |[LC0032](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0032)|Clear(All) does not affect or change values for global variables in single instance codeunits.|Warning| |[LC0033](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0033)|The specified runtime version in app.json is falling behind.|Info| +|[LC0034](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0034)|The property `Extensible` should be explicitly set for public objects.|Disabled| ## Configuration