StefanMaron / BusinessCentral.LinterCop

Community driven code linter for AL (MS Dynamics 365 Business Central)
https://stefanmaron.com
MIT License
74 stars 31 forks source link

Problem/Improvement Suggestion: Unhandled Exceptions in BCLinterCop Break ALC.exe #629

Closed DanielGoehler closed 4 months ago

DanielGoehler commented 4 months ago

Description

We are experiencing issues with the custom code cop, BCLinterCop, for the AL language extension. Unhandled exceptions within the BCLinterCop not only cause the ALC.exe to crash but also return an error code of -532462766. This causes our Azure DevOps pipelines to fail.

Current Behavior

When an unhandled exception occurs in the BCLinterCop, it breaks the ALC.exe and results in a pipeline failure. This makes it difficult to identify the root cause of the problem as the error details are insufficient.

Suggested Improvements

  1. Global Exception Handling:

    • Implement global exception handling within the BCLinterCop to catch any unhandled exceptions.
    • Ensure that these exceptions do not cause the ALC.exe to crash, allowing the pipeline to continue running.
  2. Enhanced Error Reporting:

    • Provide detailed error messages that include the specific .al file and, if possible, the exact line number where the exception occurred.
    • This will help in creating specific GitHub issues and facilitate quicker resolution of the underlying problems.

Benefits

Additional Information

[...]
*** Detect ALC.EXE Features.
##[command]& C:\bcartifacts.cache\sandbox\25.0.19932.0\VSIX\extension\bin\win32\alc.exe /?
  * PARALLEL
  * MAXDEGREEOFPARALLELISM
  * ASSEMBLYPROBINGPATHS
*** Start ALC.EXE / Compile AL Extension
##[command]& C:\bcartifacts.cache\sandbox\25.0.19932.0\VSIX\extension\bin\win32\alc.exe /packagecachepath:"C:\agent\_work\3785\s\MainApp\.ALOPSCache" /project:"C:\agent\_work\3785\s\MainApp" /out:"C:\agent\_work\3785\a\Some Company_Some App_3.0.53129.0_sandbox_25.0_de.app" /fullpaths /analyzer:"C:\bcartifacts.cache\sandbox\25.0.19932.0\vsix\extension\bin\Analyzers\Microsoft.Dynamics.Nav.AppSourceCop.dll","C:\bcartifacts.cache\sandbox\25.0.19932.0\vsix\extension\bin\Analyzers\Microsoft.Dynamics.Nav.CodeCop.dll","C:\bcartifacts.cache\sandbox\25.0.19932.0\vsix\extension\bin\Analyzers\Microsoft.Dynamics.Nav.PerTenantExtensionCop.dll","C:\bcartifacts.cache\sandbox\25.0.19932.0\vsix\extension\bin\Analyzers\Microsoft.Dynamics.Nav.UICop.dll","C:\bcartifacts.cache\sandbox\25.0.19932.0\vsix\extension\bin\Analyzers\BusinessCentral.LinterCop.dll" /ruleset:"C:\agent\_work\3785\s\MainApp\.vscode\rulesets\ruleset.json" /parallel+ /maxDegreeOfParallelism:2 /assemblyprobingpaths:"C:\Windows\assembly","C:\Windows\Microsoft.NET\assembly","C:\bcartifacts.cache\sandbox\25.0.19932.0\platform\Test Assemblies\Mock Assemblies","C:\bcartifacts.cache\sandbox\25.0.19932.0\platform\ServiceTier\program files\Microsoft Dynamics NAV\250\Service"
Unhandled exception. Unhandled exception. System.InvalidCastException: Unable to cast object of type 'Microsoft.Dynamics.Nav.CodeAnalysis.Syntax.OptionValuesSyntax' to type 'Microsoft.Dynamics.Nav.CodeAnalysis.Syntax.VarSectionSyntax'.
   at BusinessCentral.LinterCop.Design.Rule0044AnalyzeTransferFields.FindLocalVariables(SyntaxNode node)
   at BusinessCentral.LinterCop.Design.Rule0044AnalyzeTransferFields.AnalyzeTransferFields(OperationAnalysisContext ctx)
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
   at System.Threading.QueueUserWorkItemCallback.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
System.InvalidCastException: Unable to cast object of type 'Microsoft.Dynamics.Nav.CodeAnalysis.Syntax.OptionValuesSyntax' to type 'Microsoft.Dynamics.Nav.CodeAnalysis.Syntax.VarSectionSyntax'.
   at BusinessCentral.LinterCop.Design.Rule0044AnalyzeTransferFields.FindLocalVariables(SyntaxNode node)
   at BusinessCentral.LinterCop.Design.Rule0044AnalyzeTransferFields.AnalyzeTransferFields(OperationAnalysisContext ctx)
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
   at System.Threading.QueueUserWorkItemCallback.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'Microsoft.Dynamics.Nav.CodeAnalysis.Syntax.OptionValuesSyntax' to type 'Microsoft.Dynamics.Nav.CodeAnalysis.Syntax.VarSectionSyntax'.
   at BusinessCentral.LinterCop.Design.Rule0044AnalyzeTransferFields.FindLocalVariables(SyntaxNode node)
   at BusinessCentral.LinterCop.Design.Rule0044AnalyzeTransferFields.AnalyzeTransferFields(OperationAnalysisContext ctx)
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
   at System.Threading.QueueUserWorkItemCallback.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'Microsoft.Dynamics.Nav.CodeAnalysis.Syntax.OptionValuesSyntax' to type 'Microsoft.Dynamics.Nav.CodeAnalysis.Syntax.VarSectionSyntax'.
   at BusinessCentral.LinterCop.Design.Rule0044AnalyzeTransferFields.FindLocalVariables(SyntaxNode node)
   at BusinessCentral.LinterCop.Design.Rule0044AnalyzeTransferFields.AnalyzeTransferFields(OperationAnalysisContext ctx)
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
   at System.Threading.QueueUserWorkItemCallback.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'Microsoft.Dynamics.Nav.CodeAnalysis.Syntax.OptionValuesSyntax' to type 'Microsoft.Dynamics.Nav.CodeAnalysis.Syntax.VarSectionSyntax'.
   at BusinessCentral.LinterCop.Design.Rule0044AnalyzeTransferFields.FindLocalVariables(SyntaxNode node)
   at BusinessCentral.LinterCop.Design.Rule0044AnalyzeTransferFields.AnalyzeTransferFields(OperationAnalysisContext ctx)
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
   at System.Threading.QueueUserWorkItemCallback.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
*** AL Compiler Exit Code: -532462766
[...]

We are unable to share the entire AL project due to confidentiality, but we can provide more specific details if needed.

Arthurvdv commented 4 months ago

Hi @DanielGoehler,

I've added an Try/Catch around the FindLocalVariables method, so you're unblocked now and we can investigate more targeted the code responsible for this exception.

You're absolutely right on a the exception handling and I'm open for suggestion on a approach on this. Currently I'm only familiar with the Try/Catch mechanism, which come with a cost regarding performance. Otherwise we could set a Try/Catch around every rule and/or method to prevent scenario's like this? 🤔

I like follow the suggestions from @dannoe on performance and error handling (https://github.com/StefanMaron/BusinessCentral.LinterCop/issues/284#issuecomment-1861395242). Unfortunately this is not yet implemented on all the rules combined. Also some rules are moved from the CompanialCop, like the LC0044 rule here. This rule was a great gift and also a complex rule, where it's difficult to cover all possible scenario's. In this specific example I guess the ".. as or is for casting and then check for null.." is missing in the FindLocalVariables method. But I would like to see a code sample to see and test it this indeed would resolve the issue.

Arthurvdv commented 4 months ago

25.0.19932.0 Wait...this is the Next Major?

Currently we've just started supported multiple version of the AL Languages of the marketplace. Support for artifacts is more complex, as there are different versions of the AL Language in there. For example artifact 25.0.19997.0 comes with the AL Language version 14.0.1027044 which isn't available on the marketplace (yet).

image

The support for multiple AL Languages is working for VS Code. For pipelines I'm still searching for a possible solution.

DanielGoehler commented 4 months ago

@Arthurvdv Sure, I think balancing performance and reliability is important. If there is no single place for exception handling, having a template with basic exception handling would be beneficial.

Regarding the Next Major pipelines, I believe we need an ALOps extension because using alternativevsixurl: 'Latest' cannot handle the Next Major Apps either.

##[warning]error AL1153: The referenced module 'System by Microsoft (25.0.19934.0)' with runtime reference version '14.0' cannot be loaded by the compiler with version '13.0'.
##[warning]error AL1153: The referenced module 'System Application by Microsoft (25.0.19977.0)' with runtime reference version '14.0' cannot be loaded by the compiler with version '13.0'.
##[warning]error AL1153: The referenced module 'Business Foundation by Microsoft (25.0.19977.0)' with runtime reference version '14.0' cannot be loaded by the compiler with version '13.0'.
##[warning]error AL1153: The referenced module 'Base Application by Microsoft (25.0.19977.0)' with runtime reference version '14.0' cannot be loaded by the compiler with version '13.0'.
##[warning]error AL1153: The referenced module 'Application by Microsoft (25.0.19977.0)' with runtime reference version '14.0' cannot be loaded by the compiler with version '13.0'.
waldo1001 commented 4 months ago

Please tell me if this would be a solution to the above? https://github.com/HodorNV/ALOps/issues/766

DanielGoehler commented 4 months ago

@waldo1001 Thank you. This works. Left side without alternativevsixurl (ALC.exe from NextMajor) and right side with alternativevsixurl: 'Prerelease'. image

DanielGoehler commented 4 months ago

@Arthurvdv Thanks for your help. We will change our next release pipelines in ALOps to alternativevsixurl: Prerelease so that ALC.exe will no longer crash.