VS Code Extensions for AL

There is one simple principle for AL Developers.

By looking at the code, it should not be possible to see who wrote it.

You probably never heard of this.

Some History

From 1994 till 1996, I worked at Navision Software in Denmark.

I made two contributions that I am quite proud of.

  • The Demonstration Data Tool for Navision Financials. You know it as the Cronus company.
  • The Localisation and translation methodology for Navision Financials

For a period, I worked closely with Jakob Nielsen. Jakob designed the user interface for the Navision Financials 1.0 and wrote the GUI Guidelines. At the time, I was already interested in usability, but Jakob was a huge inspiration.

One of the foundational design principels is Consistency. *)

  • in layout and design.
  • in terminology.
  • in interaction
  • in user experience
  • in aesthetic design.
  • in branding.

So why should coding be any different? Let me reassure you, it is not!

Consistency in coding is fundamental for clean, easy to read and maintable code.

The purpose of this article is to guide you to the most important of these developer tools that helps you write clean and consistent code.

*) This dates back to the Apple Design Guidelines in the early nineties. We have had this for the past 30 years and it still true.

But now we have tools

In Navision and Dynamics NAV, when coding in C/AL, it was pretty much up to each developer to follow the programming guidelines. They were written in a Word document and if you were really into it, the document would be in your Desktop folder and you would check it from time to time when in doubt.

But with Visual Studio Code this has changed and in a big way.

AZ AL Dev Tools/AL Code Outline Extension

In the article Rulesets in Business Central I wrote about how to implement Rulesets to help you follow the rules. But what if there was a tool that could fix all the issues for us?

Andrzej Zwierzchowski is the author of the AZ AL Dev Tools/AL Code Outline extension to Visual Studio Code.

The extension has a lot of functionality and I am not going through all of it here. I am going to focus on the automation of keeping the code clean.

Automatic Sorting of Properties and Variables

To automatically sort the following elements each time you save your document.

  • fields in tables
  • procedures
  • variables
  • properties
  • report columns
  • permissions
  • permission sets
  • customizations actions

Find your Workspace Settings in the .vscode folder find the settings.json file and insert the following lines.

    "editor.codeActionsOnSave": {
        "source.fixAll.al": true
    },
    "alOutline.codeActionsOnSave": [
        "SortCustomizations",
        "SortPermissionSetList",
        "SortPermissions",
        "SortProperties",
        "SortReportColumns",
        "SortTableFields",
        "SortVariables",
    ],

The only one, I am not including in existing projects, is SortProcedures.

Sorting of Variables? What is going on? You might ask. The idea is not new. One less thing to think about.

Attention: Before activating this the first time, make sure you have checked in your changes and is standing in a new clean branch. This ease the roll back if needed.

Cleanup Your Project

Next is the Run Code Cleanup on the Active Project command. In Visual Studion Code, you choose View, Command Pallete, AZ AL Dev Tools: Run Code Cleanup on the Active Project.

In the .vscode folder, find the settings.json file and insert the following lines.

    "alOutline.codeCleanupActions": [
        "AddApplicationAreas",
        "AddEnumValuesCaptions",
        "AddMissingParentheses",
        "AddObjectCaptions",
        "AddTableFieldCaptions",
        "AddToolTips",
        "CollapseEmptyBrackets",
        "ConvertObjectIdsToNames",
        "FixIdentifiersCase",
        "FixKeywordsCase",
        "FormatDocument",
        "LockRemovedFieldCaptions",
        "MakeFlowFieldsReadOnly",
        "OneStatementPerLine",
        "RefreshToolTips",
        "RemoveBeginEnd",
        "RemoveEmptyLines",
        "RemoveEmptySections",
        "RemoveEmptyTriggers",
        "RemoveRedundantAppAreas",
        "RemoveRedundantDataClassification",
        "RemoveStrSubstNoFromError",
        "RemoveUnusedVariables",
        "RemoveWithStatements",
        "SortCustomizations",
        "SortPermissionSetList",
        "SortPermissions",
        "SortProperties",
        "SortReportColumns",
        "SortTableFields",
        "SortVariables",
        "TrimTrailingWhitespace"
    ],

Attention: Before running the command, make sure you have checked in your changes and is standing in a new clean branch. This ease the roll back if needed.

“alOutline.codeCleanupActions” not used

  • "AddPageFieldCaptions", The field caption should come from the table
  • "SortProcedures", not really logical. What is the sorting? Alphabetically
  • "AddDataClassifications", not sure if it is needed.
  • "RemoveUnusedVariables", and we already get the warnings. No need to remove it automatically.

I exclude the above since it could interfere with my work in progress.

Folders and file names

How should I organize my AL project? There are a lot of ideas and suggestions on this in the community. Some still want to organize by object type. Others suggest organizing by namespaces or functionality.

How should I name the root AL folder and where should I put the test folder? A lot of confusion, mixed with personal opinions and no standard guidelines.

Get some inspiration from Waldo: CRS AL Language Extension – File Management

.vscode/settings.json

The following example is there to give you an overview of the possibilities.

{
    "al.enableCodeAnalysis": true,
    "al.codeAnalyzers": [
        "${CodeCop}",
        "${UICop}",
        "${PerTenantExtensionCop}"
    ],
    "al.backgroundCodeAnalysis": "Project",
    "al.browser": "Edge",
    "al.ruleSetPath": "./.vscode/Main.ruleset.json",
    "xml.validation.namespaces.enabled": "onNamespaceEncountered",
    "xml.validation.schema.enabled": "onValidSchema",
    "CRS.FileNamePattern": "<ObjectNameShort>.<ObjectTypeShortPascalCase>.al",
    "CRS.FileNamePatternExtensions": "<ObjectNameShort>.<ObjectTypeShortPascalCase>.al",
    "CRS.FileNamePatternPageCustomizations": "<ObjectNameShort>.<ObjectTypeShortPascalCase>.al",
    "CRS.ExtensionObjectNamePattern": "",
    "CRS.AlSubFolderName": "None",
    "CRS.OnSaveAlFileAction": "Rename",
    "alOutline.codeCleanupActions": [
        "AddApplicationAreas",
        "AddEnumValuesCaptions",
        "AddMissingParentheses",
        "AddObjectCaptions",
        "AddTableFieldCaptions",
        "AddToolTips",
        "CollapseEmptyBrackets",
        "ConvertObjectIdsToNames",
        "FixIdentifiersCase",
        "FixKeywordsCase",
        "FormatDocument",
        "LockRemovedFieldCaptions",
        "MakeFlowFieldsReadOnly",
        "OneStatementPerLine",
        "RefreshToolTips",
        "RemoveBeginEnd",
        "RemoveEmptyLines",
        "RemoveEmptySections",
        "RemoveEmptyTriggers",
        "RemoveRedundantAppAreas",
        "RemoveRedundantDataClassification",
        "RemoveStrSubstNoFromError",
        "RemoveUnusedVariables",
        "RemoveWithStatements",
        "SortCustomizations",
        "SortPermissionSetList",
        "SortPermissions",
        "SortProperties",
        "SortReportColumns",
        "SortTableFields",
        "SortVariables",
        "TrimTrailingWhitespace"
    ],
    "alOutline.defaultAddPageFieldCaptionsSettings": {},
    "alOutline.webClientPort": 0,
    "alOutline.useTableFieldDescriptionAsToolTip": true,
    "alOutline.triggersNaturalOrder": [],
    "alOutline.fixCodeCopMissingParenthesesOnSave": true,
    "alOutline.fixCaseRemovesQuotesFromDataTypeIdentifiers": true,
    "alOutline.defaultRemoveEmptySectionsSettings": {
        "removeActionGroups": true,
        "removeActions": true,
        "ignoreComments": false
    },
    "linterCop.autoDownload": true
}

Clean AL Code Initiative