Casing mismatch (FC0002)

AL is case-insensitive, but consistent casing improves readability and professionalism. When referencing identifiers (variables, procedures, fields, etc.), the casing should match the original declaration.

This rule detects when the casing of a reference differs from its declaration.

A code fix is available for this diagnostic.

Example

The following code has casing mismatches:

codeunit 50100 MyCodeunit
{
    procedure MyProcedure()
    var
        CustomerName: Text;
    begin
        customername := 'Test'; // Casing mismatch [FC0002]
        MYPROCEDURE(); // Casing mismatch [FC0002]
    end;
}

To fix this, use consistent casing that matches the declaration:

codeunit 50100 MyCodeunit
{
    procedure MyProcedure()
    var
        CustomerName: Text;
    begin
        CustomerName := 'Test';
        MyProcedure();
    end;
}

Generic type arguments

FC0002 checks the casing of types used as generic type arguments inside List of [...], Dictionary of [...], and other generic type declarations. Both built-in type keywords and subtype keywords are checked:

codeunit 50100 MyCodeunit
{
    var
        Names: List of [TEXT]; // Casing mismatch: TEXT should be Text [FC0002]
        Lookup: Dictionary of [INTEGER, TEXT]; // Two casing mismatches [FC0002]
        Nested: List of [Dictionary of [Integer, TEXT]]; // [FC0002]
}

Object reference casing

FC0002 checks the casing of object names referenced in Record, Codeunit, Interface, Page, XmlPort, and other subtyped data type declarations. The object name must match the casing of the original declaration:

codeunit 50100 MyCodeunit
{
    var
        Cust: Record "MY CUSTOMER"; // Casing mismatch [FC0002]
        Svc: Codeunit "MYHELPER"; // Casing mismatch [FC0002]
}

table 50100 "My Customer"
{
    fields
    {
        field(1; "Primary Key"; Integer) { }
    }
}

codeunit 50101 MyHelper { }

This applies to global variables, local variables, parameters, and return values. Namespace-qualified references are also checked, including the casing of each namespace part:

namespace MyPublisher.MyExtension.MyAppDomain;

codeunit 50100 MyCodeunit
{
    var
        Cust: Record MYPUBLISHER.MYEXTENSION.MYAPPDOMAIN.MYTABLE; // Four casing mismatches [FC0002]
}

table 50100 MyTable
{
    fields
    {
        field(1; "Primary Key"; Integer) { }
    }
}

Object references by numeric ID (Record 50100) are not checked.

XmlPort vs Xmlport casing

The AL language intentionally uses different canonical casings for xmlports depending on the context. FC0002 follows the compiler’s own canonical names (the same names the AL Language extension’s IntelliSense suggests) rather than enforcing a single spelling:

ContextCanonical casingExample
Object declarationxmlportxmlport 50100 "My Xmlport"
Variable, parameter, or return typeXmlPortMyPort: XmlPort "My Xmlport";
Static class methods (Run, Import, Export)XmlportXmlport.Run(...)
Object access (left of ::)XmlportXmlport::"My Xmlport"
ObjectType option memberXmlPortObjectType::XmlPort

For example, this code is fully canonical, even though the same word appears in three different casings:

xmlport 50100 "My Xmlport"
{
    // ...
}

codeunit 50100 MyCodeunit
{
    procedure RunIt(MyPort: XmlPort "My Xmlport")
    begin
        Xmlport.Run(Xmlport::"My Xmlport");
    end;
}

Writing XmlPort.Run(XmlPort::"My Xmlport") triggers FC0002 on the :: expression, because the compiler’s built-in class symbol behind both the static methods and the :: object access is named Xmlport.