Skip to content

Commit

Permalink
Merge pull request #317 from StefanMaron/Rule0028CodeNavigabilityOnEv…
Browse files Browse the repository at this point in the history
…entSubscribers

Added new rule 0028 CodeNavigabilityOnEventSubscribers
  • Loading branch information
Arthurvdv authored Oct 26, 2023
2 parents 3af8396 + 234ccc0 commit 1b584bb
Show file tree
Hide file tree
Showing 6 changed files with 453 additions and 382 deletions.
16 changes: 16 additions & 0 deletions Design/Rule0023AlwaysSpecifyFieldgroups.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.Dynamics.Nav.CodeAnalysis;
using Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics;
using Microsoft.Dynamics.Nav.CodeAnalysis.Symbols;
using Microsoft.Dynamics.Nav.CodeAnalysis.Text;
using System;
using System.Collections.Immutable;
Expand All @@ -20,6 +21,7 @@ private void CheckFieldgroups(SymbolAnalysisContext ctx)
try
{
ITableTypeSymbol table = (ITableTypeSymbol)ctx.Symbol;
if (IsTableOfTypeSetupTable(table)) return;

Location FieldGroupLocation = table.GetLocation();
if (!table.Keys.IsEmpty)
Expand All @@ -40,5 +42,19 @@ private void CheckFieldgroups(SymbolAnalysisContext ctx)
ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0000ErrorInRule, ctx.Symbol.GetLocation(), new Object[] { "Rule0023", "ArgumentOutOfRangeException", "" }));
}
}

private static bool IsTableOfTypeSetupTable(ITableTypeSymbol table)
{
// Expect Primary Key to contains only one field
if (table.PrimaryKey.Fields.Length != 1) return (false);

// The field should be of type Code
if (table.PrimaryKey.Fields[0].GetTypeSymbol().GetNavTypeKindSafe() != NavTypeKind.Code) return (false);

// The field should be exactly (case sensitive) called 'Primary Key'
if (table.PrimaryKey.Fields[0].Name != "Primary Key") return (false);

return (true);
}
}
}
33 changes: 33 additions & 0 deletions Design/Rule0028CodeNavigabilityOnEventSubscribers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Microsoft.Dynamics.Nav.Analyzers.Common.AppSourceCopConfiguration;
using Microsoft.Dynamics.Nav.CodeAnalysis;
using Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics;
using Microsoft.Dynamics.Nav.CodeAnalysis.Syntax;
using System.Collections.Immutable;

namespace BusinessCentral.LinterCop.Design
{
[DiagnosticAnalyzer]
public class RuleXDescription : DiagnosticAnalyzer
{
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create<DiagnosticDescriptor>(DiagnosticDescriptors.Rule0028CodeNavigabilityOnEventSubscribers);

public override void Initialize(AnalysisContext context) => context.RegisterCodeBlockAction(new Action<CodeBlockAnalysisContext>(this.CodeNavigabilityOnEventSubscribers));

private void CodeNavigabilityOnEventSubscribers(CodeBlockAnalysisContext context)
{
// Support for using Identifiers instead of Literals in event subscribers is supported from runtime versions: '11.0' or greater.
var manifest = AppSourceCopConfigurationProvider.GetManifest(context.SemanticModel.Compilation);
if (manifest.Runtime < RuntimeVersion.Spring2023) return;

if (context.OwningSymbol.GetContainingObjectTypeSymbol().IsObsoletePending || context.OwningSymbol.GetContainingObjectTypeSymbol().IsObsoleteRemoved) return;
if (context.OwningSymbol.IsObsoletePending || context.OwningSymbol.IsObsoleteRemoved) return;

var SyntaxList = ((MethodDeclarationSyntax)context.CodeBlock).Attributes.Where(value => value.GetIdentifierOrLiteralValue().ToUpper() == "EVENTSUBSCRIBER");
foreach (var Syntax in SyntaxList)
{
if (Syntax.ArgumentList.Arguments[2].IsKind(SyntaxKind.LiteralAttributeArgument))
context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0028CodeNavigabilityOnEventSubscribers, context.OwningSymbol.GetLocation()));
}
}
}
}
5 changes: 5 additions & 0 deletions LinterCop.ruleset.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@
"id": "LC0022",
"action": "Info",
"justification": "GlobalLanguage() must be implemented through the Translation Helper codeunit from the Base Application."
},
{
"id": "LC0028",
"action": "Info",
"justification": "Event subscriber arguments now use identifier syntax instead of string literals. Convert the argument literal to an identifier."
}
]
}
3 changes: 2 additions & 1 deletion LinterCopAnalyzers.Generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ public static class DiagnosticDescriptors
public static readonly DiagnosticDescriptor Rule0021ConfirmImplementConfirmManagement = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0021", (LocalizableString)new LocalizableResourceString("Rule0021ConfirmImplementConfirmManagement", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0021ConfirmImplementConfirmManagement", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0021ConfirmImplementConfirmManagement", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0021");
public static readonly DiagnosticDescriptor Rule0022GlobalLanguageImplementTranslationHelper = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0022", (LocalizableString)new LocalizableResourceString("Rule0022GlobalLanguageImplementTranslationHelperTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0022GlobalLanguageImplementTranslationHelperFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0022GlobalLanguageImplementTranslationHelperDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0022");
public static readonly DiagnosticDescriptor Rule0023AlwaysSpecifyFieldgroups = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0023", (LocalizableString)new LocalizableResourceString("Rule0023AlwaysSpecifyFieldgroups", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0023AlwaysSpecifyFieldgroups", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0023AlwaysSpecifyFieldgroups", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0023");
public static readonly DiagnosticDescriptor Rule0028CodeNavigabilityOnEventSubscribers = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0028", (LocalizableString)new LocalizableResourceString("Rule0028CodeNavigabilityOnEventSubscribersTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0028CodeNavigabilityOnEventSubscribersFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0028CodeNavigabilityOnEventSubscribersDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0028");
}
}
}
Loading

0 comments on commit 1b584bb

Please sign in to comment.