System.NullReferenceException on GetSymbolInfo with a custom Code Analyzer
I'm unsure if this scenario is supported, as the issue occurs with a custom code analyzer and I haven't encountered it with any of the Microsoft-provided analyzers. Nevertheless, I wanted to report it here, hoping that it might be a low-hanging fruit issue and could lead to a small improvement in the CodeAnalysis library.
1. Describe the bug
The 'GetSymbolInfo' method of the Microsoft.Dynamics.Nav.CodeAnalysis.dll throws an NullReferenceException on the case of pragma directives on the example file.
2. To Reproduce I've provided a small as possible code snippet which should raise this exception.
using Microsoft.Dynamics.Nav.CodeAnalysis;
using Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;
namespace BusinessCentral.CustomCodeAnalyzer;
[DiagnosticAnalyzer]
public class MyDiagnosticAnalyzer : DiagnosticAnalyzer
{
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
= ImmutableArray.Create(DiagnosticDescriptors.MyDiagnosticAnalyzer);
public override void Initialize(AnalysisContext context) =>
context.RegisterSyntaxNodeAction(new Action<SyntaxNodeAnalysisContext>(this.AnalyzeNode), SyntaxKind.IdentifierName);
private void AnalyzeNode(SyntaxNodeAnalysisContext ctx)
{
var symbolInfo = ctx.SemanticModel.GetSymbolInfo(ctx.Node, ctx.CancellationToken); // This line causes an System.NullReferenceException
}
}
report 50000 "My Report"
{
dataset
{
dataitem(Integer; Integer)
{
#pragma warning disable AL0432
column(ContactHomePage; Contact."Home Page") { }
#pragma warning restore AL0432
}
}
var
Contact: Record Contact;
}
Analyzer 'MyCustomCodeAnalyzer.MyDiagnosticAnalyzer' threw an exception of type 'System.NullReferenceException' with message 'System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Dynamics.Nav.CodeAnalysis.BinderFactory.BinderFactoryVisitor.VisitCore(SyntaxNode node) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Binder\BinderFactory.cs:line 327
at Microsoft.Dynamics.Nav.CodeAnalysis.SyntaxVisitor`1.VisitPragmaWarningDirectiveTrivia(PragmaWarningDirectiveTriviaSyntax node) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Generated\SyntaxVisitor.Generated.cs:line 1677
at Microsoft.Dynamics.Nav.CodeAnalysis.Syntax.PragmaWarningDirectiveTriviaSyntax.Accept[TResult](SyntaxVisitor`1 visitor) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Generated\SyntaxNodes.Generated.cs:line 31636
at Microsoft.Dynamics.Nav.CodeAnalysis.BinderFactory.GetBinder(SyntaxNode node, Int32 position) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Binder\BinderFactory.cs:line 81
at Microsoft.Dynamics.Nav.CodeAnalysis.Compilation.GetBinder(SyntaxNode syntax) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Compilation\Compilation.cs:line 1526
at Microsoft.Dynamics.Nav.CodeAnalysis.ReportDataItemSemanticModel.GetSymbolInfoWorker(SyntaxNode node, CancellationToken cancellationToken) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Compilation\ReportDataItemSemanticModel.cs:line 96
at Microsoft.Dynamics.Nav.CodeAnalysis.SyntaxTreeSemanticModel.GetSymbolInfoWorker(SyntaxNode node, CancellationToken cancellationToken) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Compilation\SyntaxTreeSemanticModel.cs:line 95
at Microsoft.Dynamics.Nav.CodeAnalysis.SemanticModel.GetSymbolInfo(ExpressionSyntax expression, CancellationToken cancellationToken) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Compilation\SemanticModel.cs:line 551
at Microsoft.Dynamics.Nav.CodeAnalysis.SemanticModel.GetSymbolInfoFromNode(SyntaxNode node, CancellationToken cancellationToken) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\Compilation\SemanticModel.cs:line 409
at BusinessCentral.CustomCodeAnalyzer.RuleSomething.AnalyzeNode(SyntaxNodeAnalysisContext ctx) in C:\Users\arthur.vandevondervo\repo\BusinessCentral.LinterCop\BusinessCentral.LinterCop\Design\Test.cs:line 19
at Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics.AnalyzerExecutor.ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, Action analyze, Nullable`1 info) in X:\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\DiagnosticAnalyzer\AnalyzerExecutor.cs:line 1088'
3. Expected behavior
It would be great if the method would return a null in this example.
I had mitigated this to exclude PragmaWarningDirectiveTrivia, something like;
private void AnalyzeNode(SyntaxNodeAnalysisContext ctx)
{
if (ctx.Node.Parent.Kind != SyntaxKind.PragmaWarningDirectiveTrivia)
{
var symbolInfo = ctx.SemanticModel.GetSymbolInfo(ctx.Node, ctx.CancellationToken);
}
}
Recently another issue has occured, where I've now discovered also Preprocessor directives can cause this same exception. I have again mitigated this, but would be great if this could be handled by the GetSymbolInfo itself.
4. Actual behavior
5. Versions:
- AL Language: 15.0.1290655
- Visual Studio Code: 1.97.2
- Business Central: not applicable
- List of Visual Studio Code extensions that you have installed: not applicable
- Operating System:
- [X] Windows
- [ ] Linux
- [ ] MacOS
Final Checklist
Please remember to do the following:
- [X] Search the issue repository to ensure you are reporting a new issue
- [X] Reproduce the issue after disabling all extensions except the AL Language extension
- [X] Simplify your code around the issue to better isolate the problem