Use Code Analyzers on your AL Code in Business Central

In this video I show how to add code analyzer to a Microsoft Dynamics 365 Business Central AL project and then activate them before dealing with all issues found:

https://youtu.be/aaNRQxoMxi4

Code Analyzers will help you write better code and make sure you avoid “stupid” bugs and common mistakes.

Find more information on code analyzers here.


In this video, Erik walks through how to use code analyzers (sometimes called “code cops”) on your AL code in Business Central. He demonstrates how to enable and configure analyzers like AppSourceCop, CodeCop, and UICop, then systematically works through dozens of errors and warnings to clean up an app — fixing naming conventions, removing unused variables, preventing potential overflow bugs, adding tooltips, and more. By the end, you’ll understand how to set up code analysis on your own projects and why it’s worth doing.

Why Use Code Analyzers?

Code analyzers help you make your AL code more readable, more robust, and more predictable. They catch issues ranging from simple leftover variables to potential runtime bugs like text overflow. The analyzers that ship with the AL Language extension include:

  • CodeCop — General AL code quality rules
  • UICop — Rules related to user interface best practices
  • AppSourceCop — Rules required for apps submitted to AppSource
  • PerTenantExtensionCop — Rules for per-tenant extensions (PTEs)

Erik’s demo app is the address verification app that integrates with the US Postal Service web service (built in an earlier video series). At this stage of development, it’s the right time to clean things up.

Enabling Code Analyzers

To turn on code analyzers, go to the gear icon in Visual Studio Code and open Settings. You have two levels of settings: global (computer-wide) and workspace (per-project). Since you don’t necessarily want analyzers running on every project the same way, Erik recommends configuring them per workspace.

Navigate to Workspace > Extensions > AL Language and find the code analyzers setting. When you edit this, a settings.json file is created in your .vscode folder. Here’s what the configuration looks like:

{
  "al.codeAnalyzers": [
    "${AppSourceCop}",
    "${CodeCop}",
    "${UICop}"
  ],
  "al.enableCodeAnalysis": true,
  "al.ruleSetPath": ".alrules.json"
}

If you’re building a per-tenant extension rather than an AppSource app, you’d swap ${AppSourceCop} for ${PerTenantExtensionCop}.

The app.json Manifest

One of the first things the analyzers flag is an incomplete app.json manifest. For AppSource submissions, fields like brief, description, publisher, privacyStatement, url, and logo all need to be properly filled in. Here’s a starting point for an app.json:

{
  "id": "89c15b07-f4d3-4d80-847c-0d9b050c2b50",
  "name": "Video5",
  "publisher": "Default publisher",
  "version": "1.0.0.0",
  "brief": "",
  "description": "",
  "privacyStatement": "",
  "EULA": "",
  "help": "",
  "url": "",
  "logo": "",
  "dependencies": [
    {
      "id": "63ca2fa4-4f03-4f2b-a480-172fef340d3f",
      "publisher": "Microsoft",
      "name": "System Application",
      "version": "16.0.0.0"
    },
    {
      "id": "437dbf0e-84ff-417a-965d-ed2bb9650972",
      "publisher": "Microsoft",
      "name": "Base Application",
      "version": "16.0.0.0"
    }
  ],
  "screenshots": [],
  "platform": "16.0.0.0",
  "idRanges": [
    {
      "from": 50100,
      "to": 50149
    }
  ],
  "contextSensitiveHelpUrl": "https://Video5.com/help/",
  "showMyCode": true,
  "runtime": "5.0"
}

For AppSource, you’d also need to add the "TranslationFile" feature flag to a "features" array in this file, since translations are required.

The AppSourceCop Configuration File

The AppSourceCop requires an additional configuration file called AppSourceCop.json. This file specifies the mandatory affix (prefix or suffix) that must appear on all global object and field names. Since objects from different extensions share a global namespace in the database, this prevents naming collisions:

{
  "mandatoryAffixes": ["YourAffix"],
  "supportedCountries": ["US", "CA"]
}

Erik then goes through renaming all objects, tables, pages, codeunits, enums, and their fields/actions to include his chosen affix. Visual Studio Code’s rename feature (F2) is handy here, though for larger projects, community tools like Waldo’s renaming tools can help automate this.

The Rule Set File

Not every rule makes sense for every project, and some rules may even have false positives. The rule set file lets you customize how individual rules are handled — you can hide them, change their severity, or leave them at default. Here’s the structure:

{
  "name": "YouTube Rules",
  "description": "Rules for US Postal Service app",
  "rules": [
    {
      "id": "AA0215",
      "action": "Hidden",
      "justification": "I will choose my own file names"
    },
    {
      "id": "AA0214",
      "action": "Hidden",
      "justification": "Rule does not work correctly"
    }
  ]
}

Rule AA0215 dictates file naming conventions that Erik didn’t want to follow. Rule AA0214 flags records that “should be modified before saving to the database” — but in Erik’s case, the code was textbook correct (using Get, Validate, and Modify), and the rule was triggering incorrectly. The available actions are Hidden, None, Warning, Error, and Info.

Important: After changing these configuration files, reload the Visual Studio Code window (Developer: Reload Window) since the background AL compiler doesn’t always pick up changes to these files automatically.

Common Issues and Fixes

Unused Variables

When you refactor code — splitting functions, copying variables — it’s easy to leave unused variables behind. The analyzers catch these immediately. Here’s an example from the provided source code where the variable y is declared but never meaningfully used in a way the analyzer might flag:

local procedure GenerateAwesomeMessage(T: Date): Text
var
    d: Integer;
    m: Integer;
    y: Integer;
begin
    d := 3;
    m := 4;
    y := 5;
    newProcedure(d, m);
end;

In this case, y is assigned but never read — a classic candidate for removal. In Erik’s real app, he found several variables left over from before functions were split apart.

Missing Parentheses on Function Calls

In the old NAV style, you could write function calls without parentheses, like CompareRec.Init;. The code analyzers now prefer explicit parentheses: CompareRec.Init();. This makes it clearer that you’re invoking a function rather than referencing a property.

Possible Text Overflow

This is a real bug the analyzer caught. When assigning a Text value of unknown length into a Text[100] field, you risk a runtime overflow. The fix is to use CopyStr with MaxStrLen:

// Before (potential overflow):
MyField := GetField(XMLNode, 'SomeElement');

// After (safe):
MyField := CopyStr(GetField(XMLNode, 'SomeElement'), 1, MaxStrLen(MyField));

This ensures you only copy as many characters as the target field can hold. As Erik points out, if the US Postal Service ever returned something unexpectedly large, the app would have crashed without this fix.

Page Searchability (Usage Category)

The analyzers flag pages that don’t set the UsageCategory and ApplicationArea properties. If you don’t intend for a page to be searchable, explicitly set:

UsageCategory = None;

This prevents Microsoft from potentially making the page searchable in a future update, which could cause unexpected behavior. If you set it to anything other than None, you’ll also need to specify the ApplicationArea.

Missing Tooltips

The UICop analyzer requires tooltips on actions and fields. These are important for user experience — when someone hovers over a button or field, they should see a helpful description:

actions
{
    area(Processing)
    {
        action(VerifyAddress)
        {
            ToolTip = 'Verify the address of this customer with the US Postal Service.';
            // ...
        }
    }
}

Erik had about a dozen tooltip warnings to work through across his pages. For setup fields, tooltips should explain what the field is for, what the default value is, or where to find more information.

Progress Summary

Erik started with 78 issues (22 errors and 56 warnings) and systematically worked through them:

  1. AppSource manifest fixes (translation flag, brief, description, URLs, logo) — brought it from 78 down to about 70
  2. Mandatory affix renaming of all objects, fields, and actions — down to 56
  3. Hiding inapplicable rules (file naming and a broken record-modification rule) — down to 40
  4. Removing unused variables, adding parentheses, fixing overflow bugs, setting UsageCategory — down to about 25
  5. Adding tooltips to all actions and fields — down to zero

Conclusion

Code analyzers in AL are an essential tool for building quality Business Central extensions. They help you:

  • Find potential programming bugs — like the text overflow that would have crashed the app
  • Clean up leftovers — unused variables from refactoring
  • Set required properties — like UsageCategory, tooltips, and application areas
  • Meet AppSource requirements — mandatory affixes, translations, and manifest fields

Erik recommends having all analyzers turned on as the default for every app, with a rule set file to disable the few rules that don’t work correctly or don’t apply to your situation. The small upfront investment in fixing these warnings pays off with cleaner, more robust, and more maintainable code.