diff --git a/Design/Rule0048ErrorWithTextConstant.cs b/Design/Rule0048ErrorWithTextConstant.cs new file mode 100644 index 00000000..04c749c5 --- /dev/null +++ b/Design/Rule0048ErrorWithTextConstant.cs @@ -0,0 +1,34 @@ +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 Rule0048ErrorWithTextConstant : DiagnosticAnalyzer + { + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagnosticDescriptors.Rule0048ErrorWithTextConstant); + + public override void Initialize(AnalysisContext context) => context.RegisterOperationAction(new Action(this.AnalyzeErrorMethod), OperationKind.InvocationExpression); + + private void AnalyzeErrorMethod(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 (!SemanticFacts.IsSameName(operation.TargetMethod.Name, "Error")) return; + if (operation.Arguments.Length == 0) return; + + if (operation.Arguments[0].Syntax.Kind != SyntaxKind.IdentifierName) return; + if (operation.Arguments[0].Value.Type.GetNavTypeKindSafe() == NavTypeKind.ErrorInfo) return; + + IOperation operand = ((IConversionExpression)operation.Arguments[0].Value).Operand; + if (operand.GetSymbol().OriginalDefinition.GetTypeSymbol().GetNavTypeKindSafe() == NavTypeKind.Label) return; + + ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0048ErrorWithTextConstant, ctx.Operation.Syntax.GetLocation())); + } + } +} \ No newline at end of file diff --git a/LinterCop.ruleset.json b/LinterCop.ruleset.json index bd48a7e1..a0ab137c 100644 --- a/LinterCop.ruleset.json +++ b/LinterCop.ruleset.json @@ -236,6 +236,11 @@ "id": "LC0047", "action": "Info", "justification": "Locked Label must have a suffix Tok." + }, + { + "id": "LC0048", + "action": "Info", + "justification": "Use Error with a ErrorInfo or Label variable to improve telemetry details." } ] } \ No newline at end of file diff --git a/LinterCopAnalyzers.Generated.cs b/LinterCopAnalyzers.Generated.cs index 9a63d822..0acb45a0 100644 --- a/LinterCopAnalyzers.Generated.cs +++ b/LinterCopAnalyzers.Generated.cs @@ -54,5 +54,6 @@ public static class DiagnosticDescriptors public static readonly DiagnosticDescriptor Rule0045ZeroEnumValueReservedForEmpty = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0045", (LocalizableString)new LocalizableResourceString("Rule0045ZeroEnumValueReservedForEmptyTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0045ZeroEnumValueReservedForEmptyFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0045ZeroEnumValueReservedForEmptyDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0045"); public static readonly DiagnosticDescriptor Rule0046TokLabelsLocked = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0046", (LocalizableString)new LocalizableResourceString("Rule0046TokLabelsLockedTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0046TokLabelsLockedFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0046TokLabelsLockedDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0046"); public static readonly DiagnosticDescriptor Rule0047LockedLabelsTok = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0047", (LocalizableString)new LocalizableResourceString("Rule0047LockedLabelsTokTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0047LockedLabelsTokFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0047LockedLabelsTokDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0047"); + public static readonly DiagnosticDescriptor Rule0048ErrorWithTextConstant = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0048", (LocalizableString)new LocalizableResourceString("Rule0048ErrorWithTextConstantTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0048ErrorWithTextConstantFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0048ErrorWithTextConstantDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0048"); } } \ No newline at end of file diff --git a/LinterCopAnalyzers.resx b/LinterCopAnalyzers.resx index e14a99ad..4d0b21df 100644 --- a/LinterCopAnalyzers.resx +++ b/LinterCopAnalyzers.resx @@ -537,4 +537,13 @@ Locked Label must have a suffix Tok. + + Use Error with a ErrorInfo or Label variable to improve telemetry details. + + + Use Error with a ErrorInfo or Label variable to improve telemetry details. + + + Use Error with a ErrorInfo or Label variable to improve telemetry details. + \ No newline at end of file diff --git a/README.md b/README.md index d86f7992..3961acd2 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ Further note that you should have BcContainerHelper version 2.0.16 (or newer) in |[LC0045](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0045)|Zero (0) `Enum` value should be reserved for Empty Value.|Info| |[LC0046](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0046)|`Label` with suffix Tok must be locked.|Info| |[LC0047](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0047)|Locked `Label` must have a suffix Tok.|Info| +|[LC0048](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0048)|Use Error with a `ErrorInfo` or `Label` variable to improve telemetry details.|Info| ## Configuration