Skip to content

Conversation

@garazdawi
Copy link
Owner

@garazdawi garazdawi commented Jun 9, 2025

Summary by Sourcery

Introduce a unified diagnostics framework to replace and modernize error and warning handling across the compiler, standard library, and tools.

New Features:

  • Add erl_diagnostic module for structured emission, storage, and reporting of diagnostics (errors, warnings, info, hints)
  • Expose application:get_diagnostic/1, /2, explain/print_explain to retrieve and show diagnostic metadata and long explanations
  • Support -explain flag in erlc and runtime init to print detailed diagnostic explanations

Enhancements:

  • Refactor erl_lint, compile, dialyzer, beam_ssa_recv, and related modules to use the new diagnostics API instead of legacy error/warning lists
  • Integrate diagnostic codes and links into formatted output, JSON reports, and ANSI terminal output
  • Update application_controller to include documentation_url for apps and list available diagnostics

Documentation:

  • Add diagnostic markdown files under lib/compiler/doc/diagnostics and configure ExDoc to include them in the generated documentation
  • Extend shell_docs with render_markdown/1 to display diagnostic documents as formatted text in the REPL

@sourcery-ai
Copy link

sourcery-ai bot commented Jun 9, 2025

Reviewer's Guide

This PR introduces a unified diagnostics subsystem (erl_diagnostic) and refactors the linting and compilation toolchain to use structured diagnostic state instead of ad-hoc error/warning lists, adds user-facing explanation commands and documentation integration, and wires the new diagnostics into the CLI, application controller, and build scripts.

Sequence Diagram for Compilation Diagnostics Flow

sequenceDiagram
    participant CLI as erlc/User
    participant Compile as compile_module
    participant Lint as erl_lint_module
    participant Diag as erl_diagnostic_subsystem

    CLI->>+Compile: compile_source(File, Options)
    Compile->>+Diag: init(Options) # diagnostics_state
    Note over Compile,Diag: Diagnostics state created
    Compile->>+Lint: module(Forms, File, Opts, diagnostics_state)
    Lint->>Lint: Perform linting checks
    alt Issue found
        Lint->>+Diag: emit(diagnostics_state, key, location, args, opts)
        Diag-->>-Lint: updated_diagnostics_state
    end
    Lint-->>-Compile: updated_diagnostics_state
    Compile->>+Diag: get_errors(updated_diagnostics_state)
    Diag-->>-Compile: errors_list
    Compile->>+Diag: get_warnings(updated_diagnostics_state)
    Diag-->>-Compile: warnings_list
    alt report_errors or report_warnings enabled
        Compile->>+Diag: report(output_device, updated_diagnostics_state, format, report_opts)
        Diag-->>-Compile: status
    end
    Compile-->>-CLI: Compilation result (ok/error with diags)
Loading

ER Diagram for Core Data Structure Changes

erDiagram
    "erl_diagnostic_state" {
        opaque state "Centralized diagnostic data"
    }
    "compile_record (#compile)" {
        erl_diagnostic_state diagnostics "Replaces errors, warnings lists"
        list options
        atom module
        string ifile
        string ofile
    }
    "lint_record (#lint)" {
        erl_diagnostic_state diagnostics "Replaces errors, warnings, enabled_warnings"
        string file
        list compile_options
        gb_sets defined_functions
    }
    "application_controller_record (#appl)" {
        string documentation_url "New field for diagnostic doc URL"
        atom name
        list appl_data
        list inc_apps
    }
    "DiagnosticInfoMap (application:get_diagnostic)" {
        atom application
        string filename
        string url
        string short_code
        string long_code
        binary diagnostic_doc_content
    }

    "compile_record (#compile)" o|--|| "erl_diagnostic_state" : uses
    "lint_record (#lint)" o|--|| "erl_diagnostic_state" : uses
Loading

Class Diagram for erl_lint Module Changes

classDiagram
    class erl_lint {
        -diagnostics: erl_diagnostic_state
        -errors: list (removed)
        -warnings: list (removed)
        -enabled_warnings: list (removed)
        -warn_format: int (removed)
        +module(Forms, FileName, Opts, DiagnosticsState): NewDiagnosticsState
        +diagnostics(): list_of_diagnostic_definitions
        +start1(File, Opts, InitialDiag): lint_state (modified from start/2)
        +parse_options(Opts, DiagnosticsState): DiagnosticsState (modified)
        +is_warn_enabled(Type, lint_state): boolean (modified)
        +return_status(lint_state): result (modified)
        +add_lint_diag(ErrorOrWarning, Anno, lint_state): lint_state (new, replaces add_error/add_warning)
        +form(Form, lint_state): lint_state (modified)
        -bool_options() (removed)
        -pack_errors(Errors) (removed)
        -pack_warnings(Warnings) (removed)
    }
    note for erl_lint "Error/warning handling refactored to use erl_diagnostic_state."
Loading

Class Diagram for compile Module Changes

classDiagram
    class compile {
        -diagnostics: erl_diagnostic_state (replaces errors, warnings in #compile record)
        +emit_errors(state, Errors): new_state
        +emit_error(state, Location, Module, Reason): new_state
        +emit_warnings(state, Warnings): new_state
        +internal_comp(Passes, Code, File, Suffix, state): result (modified)
        +fold_comp(PassList, Run, Code, state): result (modified)
        +comp_ret_ok(Code, state): tuple_result (modified)
        +comp_ret_err(state): error_result (modified)
        +werror(state): boolean (modified)
        +select_passes(PassSpecList, Opts): PassList (modified for module/3 passes)
        +lint_module(Code, state): result (modified to use erl_lint:module/4)
        +core_lint_module(Code, state): result (modified)
        -messages_per_file(Messages) (removed)
        -report_errors(state) (removed)
        -report_warnings(state) (removed)
    }
    note for compile "Error/warning lists in #compile record replaced by erl_diagnostic_state. Reporting uses erl_diagnostic."
Loading

File-Level Changes

Change Details Files
Introduce a centralized diagnostics API and engine
  • Add a new module erl_diagnostic.erl with init/emit/report and legacy adapters
  • Define diagnostic types, collect state, format JSON/ANSI output, and support related annotations
  • Provide functions for querying and dumping diagnostic contexts
lib/stdlib/src/erl_diagnostic.erl
Refactor erl_lint to emit diagnostics
  • Add module/4 and start1 to carry diagnostics state
  • Replace internal errors/warnings lists with a diagnostics map and emit calls
  • Update parse_options, add_error/add_warning, return_status to use erl_diagnostic
lib/stdlib/src/erl_lint.erl
Integrate diagnostics into the compiler core
  • Extend the compile record to include diagnostics and adjust build_compile
  • Replace messages_per_file and legacy errors/warnings accumulation with diagnostics.emit
  • Update comp_ret_ok/error, select_passes, lint_module to propagate diagnostic state
lib/compiler/src/compile.erl
Propagate diagnostics through beam_ssa_recv
  • Change module/2→module/3 to accept diagnostics
  • Use erl_diagnostic.emit to record recv_opt_info warnings
  • Thread the diagnostics state through scan and optimize paths
lib/compiler/src/beam_ssa_recv.erl
Add application:get_diagnostic/explain API
  • Expose get_diagnostic/1/2, explain, print_explain in application.erl
  • Extend application_controller with available_applications and documentation_url fields
  • Support -explain boot arg in init.erl to print diagnostics descriptions
lib/kernel/src/application.erl
lib/kernel/src/application_controller.erl
erts/preloaded/src/init.erl
Enhance CLI and documentation for diagnostics
  • Add -explain option to erl_compile/erlc and emit info messages
  • Extend shell_docs with render_markdown to display diagnostic docs
  • Update doc.mk and ex_doc.exs to include diagnostic-index/*.md files
lib/stdlib/src/erl_compile.erl
make/doc.mk
make/ex_doc.exs
lib/stdlib/src/shell_docs.erl

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@garazdawi garazdawi force-pushed the lukas/stdlib/io_ansi branch 6 times, most recently from b17ffb1 to a6e4754 Compare June 17, 2025 08:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants