Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iq based exporter, using cargo json data #275

Merged
main from
Dec 13, 2024

Conversation

Canop
Copy link
Owner

This adds a new exporter category allowing analyzers do produce the exported file.

The cargo_json analyzer exports the data of cargo's metadata Diagnostic and DiagnosticSpan, one line per span with a "field path" based syntax.

The bacon.toml file has an example of such export:

# an example of export based on the JSON export, active when
# the analyzer is "cargo_json"
[exports.cargo-json-spans]
auto = false
exporter = "analyzer"
path = "bacon-analyser-export.json"
line_format = "{span.file_name} {span.line_start}-{span.line_end} | {diagnostic.message} [{diagnostic.code}] level={diagnostic.level}"

Fix #249

@CorvusPrudens
Copy link

I'm probably doing something wrong, but I can't get bacon to export the analysis. I've defined this job and export:

[jobs.bacon-ls]
command = ["cargo", "clippy", "--message-format", "json"]
analyzer = "cargo_json"

[exports.cargo-json-spans]
auto = true
exporter = "analyzer"
line_format = "{diagnostic.level}:{span.file_name}:{span.line_start}:{span.line_end}:{span.col_start}:{span.col_end}:{diagnostic.message}"

The bacon UI is empty when the job runs and completes, and the log with a level of info produces this:

Bacon log
13:12:06.721 [INFO] cli_log::init: Starting bacon v3.5.0-dev with log level INFO
13:12:06.722 [INFO] bacon::cli: args: Args {
    help: false,
    version: false,
    prefs: false,
    summary: false,
    no_summary: false,
    wrap: false,
    no_wrap: false,
    reverse: false,
    no_reverse: false,
    help_line: false,
    no_help_line: false,
    list_jobs: false,
    offline: false,
    init: false,
    job: Some(
        ConcreteJobRef {
            name_or_alias: Name(
                "bacon-ls",
            ),
            scope: Scope {
                tests: [],
            },
        },
    ),
    no_default_features: false,
    features: None,
    all_features: false,
    export_locations: false,
    no_export_locations: false,
    path: None,
    args: [],
    additional_job_args: [],
}
13:12:06.927 [INFO] bacon::conf::settings: config loaded from "/home/corvus/.config/bacon/prefs.toml"
13:12:06.927 [INFO] bacon::conf::settings: settings: Settings {
    additional_alias_args: None,
    additional_job_args: [],
    all_features: false,
    arg_job: Some(
        ConcreteJobRef {
            name_or_alias: Name(
                "bacon-ls",
            ),
            scope: Scope {
                tests: [],
            },
        },
    ),
    config_files: [
        "/home/corvus/.config/bacon/prefs.toml",
    ],
    default_job: ConcreteJobRef {
        name_or_alias: Name(
            "check",
        ),
        scope: Scope {
            tests: [],
        },
    },
    default_watch: true,
    exports: ExportsSettings {
        exports: {
            "analysis": ExportSettings {
                exporter: Analysis,
                auto: false,
                path: "bacon-analysis.json",
                line_format: "",
            },
            "cargo-json-spans": ExportSettings {
                exporter: Analyser,
                auto: true,
                path: "bacon-analyser.json",
                line_format: "{diagnostic.level}:{span.file_name}:{span.line_start}:{span.line_end}:{span.col_start}:{span.col_end}:{diagnostic.message}",
            },
            "json-report": ExportSettings {
                exporter: JsonReport,
                auto: false,
                path: "bacon-report.json",
                line_format: "",
            },
        },
    },
    features: None,
    grace_period: Period {
        duration: 5ms,
    },
    help_line: true,
    ignore: [],
    ignored_lines: None,
    jobs: {
        "nextest": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: Some(
                Nextest,
            ),
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "nextest",
                "run",
                "--hide-progress-bar",
                "--failure-output",
                "final",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: true,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "bacon-ls": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: Some(
                CargoJson,
            ),
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "clippy",
                "--message-format",
                "json",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "check": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "check",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "check-all": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "check",
                "--all-targets",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "doc-open": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "doc",
                "--no-deps",
                "--open",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: Some(
                Internal(
                    Back,
                ),
            ),
            watch: None,
        },
        "doc": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "doc",
                "--no-deps",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "run": Job {
            allow_failures: false,
            allow_warnings: true,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "run",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: true,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "run-long": Job {
            allow_failures: false,
            allow_warnings: true,
            analyzer: None,
            apply_gitignore: None,
            background: false,
            command: [
                "cargo",
                "run",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: true,
            on_change_strategy: Some(
                KillThenRestart,
            ),
            on_success: None,
            watch: None,
        },
        "clippy": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "clippy",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "ex": Job {
            allow_failures: false,
            allow_warnings: true,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "run",
                "--example",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: true,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "test": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "test",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: true,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "clippy-all": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "clippy",
                "--all-targets",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
    },
    keybindings: KeyBindings {
        h: "help",
        w: "toggle-wrap",
        Ctrl-e: "export:analysis",
        Home: "scroll-to-top",
        p: "toggle-pause",
        r: "job:run",
        Ctrl-u: "scroll-pages(-1)",
        Up: "scroll-lines(-1)",
        ?: "help",
        s: "toggle-summary",
        Esc: "back",
        i: "job:initial",
        j: "scroll-lines(1)",
        g: "scroll-to-top",
        PageDown: "scroll-pages(1)",
        Ctrl-d: "scroll-pages(1)",
        q: "quit",
        c: "job:clippy-all",
        t: "job:test",
        f: "scope-to-failures",
        d: "job:doc-open",
        F5: "refresh",
        PageUp: "scroll-pages(-1)",
        Down: "scroll-lines(1)",
        Ctrl-c: "quit",
        Ctrl-q: "quit",
        b: "toggle-backtrace(1)",
        End: "scroll-to-bottom",
        n: "job:nextest",
        k: "scroll-lines(-1)",
        a: "job:check-all",
        Space: "scroll-pages(.8)",
        Shift-g: "scroll-to-bottom",
    },
    no_default_features: false,
    on_change_strategy: None,
    reverse: false,
    show_changes_count: false,
    summary: false,
    watch: [],
    wrap: true,
    env: {
        "CARGO_TERM_COLOR": "always",
    },
}
13:12:06.934 [INFO] bacon::app: mission.ignorer() took 255.72µs
13:12:06.936 [INFO] bacon::exec::executor: start task Task { backtrace: None, grace_period: Period { duration: 5ms } }
13:12:09.464 [INFO] bacon::app: execution finished with status: Some(ExitStatus(unix_wait_status(25856)))
13:12:09.464 [INFO] bacon::export::exports_settings: doing auto export "cargo-json-spans"
13:12:09.464 [INFO] bacon::export::export_settings: exporting to "/home/corvus/Documents/github/pers/bell-web/bacon-analyser.json"
13:12:09.464 [INFO] bacon::export::export_settings: No report to export
13:13:28.406 [INFO] bacon::watcher: ignorer.excludes_all_pathbufs(&we.paths) took 200ns
13:13:28.407 [INFO] bacon::app: config watch event received
13:13:28.407 [INFO] bacon::conf::settings: config loaded from "/home/corvus/.config/bacon/prefs.toml"
13:13:28.407 [INFO] bacon::conf::settings: settings: Settings {
    additional_alias_args: None,
    additional_job_args: [],
    all_features: false,
    arg_job: Some(
        ConcreteJobRef {
            name_or_alias: Name(
                "bacon-ls",
            ),
            scope: Scope {
                tests: [],
            },
        },
    ),
    config_files: [
        "/home/corvus/.config/bacon/prefs.toml",
    ],
    default_job: ConcreteJobRef {
        name_or_alias: Name(
            "check",
        ),
        scope: Scope {
            tests: [],
        },
    },
    default_watch: true,
    exports: ExportsSettings {
        exports: {
            "analysis": ExportSettings {
                exporter: Analysis,
                auto: false,
                path: "bacon-analysis.json",
                line_format: "",
            },
            "json-report": ExportSettings {
                exporter: JsonReport,
                auto: false,
                path: "bacon-report.json",
                line_format: "",
            },
            "cargo-json-spans": ExportSettings {
                exporter: Analyser,
                auto: true,
                path: "bacon-analyser.json",
                line_format: "{diagnostic.level}:{span.file_name}:{span.line_start}:{span.line_end}:{span.col_start}:{span.col_end}:{diagnostic.message}",
            },
        },
    },
    features: None,
    grace_period: Period {
        duration: 5ms,
    },
    help_line: true,
    ignore: [],
    ignored_lines: None,
    jobs: {
        "check-all": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "check",
                "--all-targets",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "clippy-all": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "clippy",
                "--all-targets",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "nextest": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: Some(
                Nextest,
            ),
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "nextest",
                "run",
                "--hide-progress-bar",
                "--failure-output",
                "final",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: true,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "check": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "check",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "doc": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "doc",
                "--no-deps",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "test": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "test",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: true,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "run-long": Job {
            allow_failures: false,
            allow_warnings: true,
            analyzer: None,
            apply_gitignore: None,
            background: false,
            command: [
                "cargo",
                "run",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: true,
            on_change_strategy: Some(
                KillThenRestart,
            ),
            on_success: None,
            watch: None,
        },
        "bacon-ls": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: Some(
                CargoJson,
            ),
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "clippy",
                "--message-format",
                "json",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "run": Job {
            allow_failures: false,
            allow_warnings: true,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "run",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: true,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "clippy": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "clippy",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "ex": Job {
            allow_failures: false,
            allow_warnings: true,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "run",
                "--example",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: true,
            on_change_strategy: None,
            on_success: None,
            watch: None,
        },
        "doc-open": Job {
            allow_failures: false,
            allow_warnings: false,
            analyzer: None,
            apply_gitignore: None,
            background: true,
            command: [
                "cargo",
                "doc",
                "--no-deps",
                "--open",
            ],
            default_watch: None,
            env: {},
            expand_env_vars: true,
            extraneous_args: true,
            ignore: [],
            ignored_lines: None,
            kill: None,
            need_stdout: false,
            on_change_strategy: None,
            on_success: Some(
                Internal(
                    Back,
                ),
            ),
            watch: None,
        },
    },
    keybindings: KeyBindings {
        s: "toggle-summary",
        Esc: "back",
        Down: "scroll-lines(1)",
        Ctrl-c: "quit",
        a: "job:check-all",
        c: "job:clippy-all",
        h: "help",
        n: "job:nextest",
        i: "job:initial",
        Ctrl-u: "scroll-pages(-1)",
        q: "quit",
        d: "job:doc-open",
        t: "job:test",
        k: "scroll-lines(-1)",
        p: "toggle-pause",
        F5: "refresh",
        End: "scroll-to-bottom",
        f: "scope-to-failures",
        Ctrl-e: "export:analysis",
        Space: "scroll-pages(.8)",
        Home: "scroll-to-top",
        Up: "scroll-lines(-1)",
        PageUp: "scroll-pages(-1)",
        w: "toggle-wrap",
        Ctrl-d: "scroll-pages(1)",
        r: "job:run",
        j: "scroll-lines(1)",
        ?: "help",
        Shift-g: "scroll-to-bottom",
        b: "toggle-backtrace(1)",
        PageDown: "scroll-pages(1)",
        g: "scroll-to-top",
        Ctrl-q: "quit",
    },
    no_default_features: false,
    on_change_strategy: None,
    reverse: false,
    show_changes_count: false,
    summary: false,
    watch: [],
    wrap: true,
    env: {
        "CARGO_TERM_COLOR": "always",
    },
}
13:13:28.421 [INFO] bacon::app: mission.ignorer() took 326.022µs
13:13:28.424 [INFO] bacon::exec::executor: start task Task { backtrace: None, grace_period: Period { duration: 5ms } }
13:13:30.907 [INFO] bacon::app: execution finished with status: Some(ExitStatus(unix_wait_status(25856)))
13:13:30.907 [INFO] bacon::export::exports_settings: doing auto export "cargo-json-spans"
13:13:30.907 [INFO] bacon::export::export_settings: exporting to "</path/to>/bacon-analyser.json"
13:13:30.907 [INFO] bacon::export::export_settings: No report to export

Let me know if anything if obviously incorrect, here!

Copy link
Owner Author

@CorvusPrudens

Change your job definition to

[jobs.bacon-ls]
command = [
    "cargo", "clippy",
	"--message-format", "json-diagnostic-rendered-ansi",
]
analyzer = "cargo_json"
need_stdout = true

Copy link
Owner Author

If it's confirmed this (analyzer+exporter) pair is useful, I'll work on improving the logs when the command output doesn't match the analyzer expectation.

d35cb74 into main Dec 13, 2024
@crisidev
Copy link
Contributor

I am having troubles understanding how to configure bacon to produce the export location. I have tried with this config

[jobs.bacon-ls]
command = [
    "cargo", "clippy",
    "--message-format", "json-diagnostic-rendered-ansi",
]
analyzer = "cargo_json"
need_stdout = true

[exports.cargo-json-spans]
auto = true
exporter = "Locations"
line_format = "{diagnostic.level}:{span.file_name}:{span.line_start}:{span.line_end}:{span.col_start}:{span.col_end}:{diagnostic.message}"

But the location file contains only colons:

::::::
::::::

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.

Consider parsing JSON output from check and clippy
3 participants