Skip to main content
The Diagnostic class represents errors, warnings, and informational messages produced during parsing and analysis of Lua code. Each diagnostic includes information about what went wrong, where it occurred, and how severe the issue is.

Key Properties

Id

A unique identifier for the diagnostic. For Loretta diagnostics, this follows the format LUA#### (e.g., LUA0001, LUA1001).
public abstract string Id { get; }

Location

The primary location where the diagnostic occurred in the source code.
public abstract Location Location { get; }
The Location class provides:
  • SourceTree: The syntax tree containing the diagnostic
  • SourceSpan: The text span (start/end positions) of the issue
  • GetLineSpan(): Line and column information for display

Severity

The effective severity of the diagnostic.
public abstract DiagnosticSeverity Severity { get; }
Possible values from the DiagnosticSeverity enum:
  • Error (3): Something not allowed by the language rules
  • Warning (2): Something suspicious but allowed
  • Info (1): Informational message, not prescriptive
  • Hidden (0): An issue not surfaced through normal means

Descriptor

The diagnostic descriptor that provides metadata about this type of diagnostic.
public abstract DiagnosticDescriptor Descriptor { get; }
See DiagnosticDescriptor for more details.

Methods

GetMessage

Returns the human-readable diagnostic message.
public abstract string GetMessage(IFormatProvider? formatProvider = null)
Parameters:
  • formatProvider: Optional culture-specific formatting information

Getting Diagnostics from a Syntax Tree

The most common way to access diagnostics is through the GetDiagnostics() method on syntax nodes and trees:
using Loretta.CodeAnalysis;
using Loretta.CodeAnalysis.Lua;
using Loretta.CodeAnalysis.Text;

// Parse some Lua code
var tree = LuaSyntaxTree.ParseText(@"
local x = 1.0e999  -- Number too large
if then end        -- Syntax error
");

// Get all diagnostics from the tree
var diagnostics = tree.GetDiagnostics();

foreach (var diagnostic in diagnostics)
{
    Console.WriteLine($"{diagnostic.Id}: {diagnostic.GetMessage()}");
    Console.WriteLine($"  at {diagnostic.Location.GetLineSpan()}");
    Console.WriteLine($"  Severity: {diagnostic.Severity}");
}

Filtering Diagnostics by Severity

You can filter diagnostics to show only errors, warnings, or other severity levels:
var tree = LuaSyntaxTree.ParseText(luaCode);
var diagnostics = tree.GetDiagnostics();

// Get only errors
var errors = diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error);

// Get errors and warnings
var errorsAndWarnings = diagnostics.Where(d => 
    d.Severity == DiagnosticSeverity.Error || 
    d.Severity == DiagnosticSeverity.Warning);

// Check if there are any errors
if (errors.Any())
{
    Console.WriteLine("Compilation failed with errors.");
}

Formatting Diagnostics for Display

Here’s an example of formatting diagnostics in a user-friendly way:
public static void DisplayDiagnostic(Diagnostic diagnostic)
{
    var lineSpan = diagnostic.Location.GetLineSpan();
    var severity = diagnostic.Severity switch
    {
        DiagnosticSeverity.Error => "error",
        DiagnosticSeverity.Warning => "warning",
        DiagnosticSeverity.Info => "info",
        DiagnosticSeverity.Hidden => "hidden",
        _ => "unknown"
    };

    // Format: file.lua(10,5): error LUA1001: Syntax error
    Console.WriteLine(
        $"{lineSpan.Path}({lineSpan.StartLinePosition.Line + 1}," +
        $"{lineSpan.StartLinePosition.Character + 1}): " +
        $"{severity} {diagnostic.Id}: {diagnostic.GetMessage()}");
}

Common Diagnostic IDs

Loretta uses diagnostic IDs in the format LUA####. Some common ones include:

Lexer Errors (1-999)

  • LUA0001: Invalid string escape sequence
  • LUA0003: Unfinished string
  • LUA0004: Invalid number format
  • LUA0005: Numeric literal too large
  • LUA0014: Bad character
  • LUA0015: Unexpected token

Parser Errors (1000-1999)

  • LUA1000: Identifier expected (keyword used)
  • LUA1001: Identifier expected
  • LUA1002: Semicolon expected
  • LUA1003: Close parenthesis expected
  • LUA1004: Left brace expected
  • LUA1005: Right brace expected
  • LUA1006: Syntax error
  • LUA1010: Expression expected
  • LUA1012: Invalid statement
The exact diagnostic IDs are defined in the ErrorCode enum in Loretta’s source code. Version-specific diagnostics are also available for features not supported in certain Lua versions.

Additional Properties

AdditionalLocations

Other locations related to the diagnostic, typically referencing related items mentioned in the message.
public abstract IReadOnlyList<Location> AdditionalLocations { get; }

DefaultSeverity

The default severity from the diagnostic’s descriptor (may differ from effective severity).
public virtual DiagnosticSeverity DefaultSeverity { get; }

IsWarningAsError

Indicates whether this is a warning being treated as an error.
public bool IsWarningAsError { get; }

IsSuppressed

Indicates whether the diagnostic has been suppressed.
public abstract bool IsSuppressed { get; }

Creating Custom Diagnostics

You can create custom diagnostics using the static Create method:
var descriptor = new DiagnosticDescriptor(
    id: "CUSTOM001",
    title: "Custom warning",
    messageFormat: "Found issue: {0}",
    category: "Custom",
    defaultSeverity: DiagnosticSeverity.Warning,
    isEnabledByDefault: true
);

var location = Location.Create(
    syntaxTree,
    textSpan
);

var diagnostic = Diagnostic.Create(
    descriptor,
    location,
    "problematic code"
);

See Also

Build docs developers (and LLMs) love