ruff/crates/ruff_dev/src/main.rs
Micha Reiser 26c37b1e0e
Add knot.toml schema (#15735)
## Summary

Adds a JSON schema generation step for Red Knot. This PR doesn't yet add
a publishing step because it's still a bit early for that


## Test plan

I tested the schema in Zed, VS Code and PyCharm:

* PyCharm: You have to manually add a schema mapping (settings JSON
Schema Mappings)
* Zed and VS code support the inline schema specification

```toml
#:schema /Users/micha/astral/ruff/knot.schema.json


[environment]
extra-paths = []


[rules]
call-possibly-unbound-method = "error"
unknown-rule = "error"

# duplicate-base = "error"
```

```json
{
    "$schema": "file:///Users/micha/astral/ruff/knot.schema.json",

    "environment": {
        "python-version": "3.13",
        "python-platform": "linux2"
    },

    "rules": {
        "unknown-rule": "error"
    }
}
```


https://github.com/user-attachments/assets/a18fcd96-7cbe-4110-985b-9f1935584411


The Schema overall works but all editors have their own quirks:

* PyCharm: Hovering a name always shows the section description instead
of the description of the specific setting. But it's the same for other
settings in `pyproject.toml` files 🤷
* VS Code (JSON): Using the generated schema in a JSON file gives
exactly the experience I want
* VS Code (TOML): 
* Properties with multiple possible values are repeated during
auto-completion without giving any hint how they're different. ![Screen
Shot 2025-02-06 at 14 05 35
PM](https://github.com/user-attachments/assets/d7f3c2a9-2351-4226-9fc1-b91aa192a237)
* The property description mushes together the description of the
property and the value, which looks sort of ridiculous. ![Screen Shot
2025-02-06 at 14 04 40
PM](https://github.com/user-attachments/assets/8b72f04a-c62a-49b5-810f-7ddd472884d0)
* Autocompletion and documentation hovering works (except the
limitations mentioned above)
* Zed:
* Very similar to VS Code with the exception that it uses the
description attribute to distinguish settings with multiple possible
values ![Screen Shot 2025-02-06 at 14 08 19
PM](https://github.com/user-attachments/assets/78a7f849-ff4e-44ff-8317-708eaf02dc1f)


I don't think there's much we can do here other than hope (or help)
editors improve their auto completion. The same short comings also apply
to ruff, so this isn't something new. For now, I think this is good
enough
2025-02-07 10:59:40 +01:00

113 lines
4.1 KiB
Rust

//! This crate implements an internal CLI for developers of Ruff.
//!
//! Within the ruff repository you can run it with `cargo dev`.
use anyhow::Result;
use clap::{Parser, Subcommand};
use ruff::{args::GlobalConfigArgs, check};
use ruff_linter::logging::set_up_logging;
use std::process::ExitCode;
mod format_dev;
mod generate_all;
mod generate_cli_help;
mod generate_docs;
mod generate_json_schema;
mod generate_knot_schema;
mod generate_options;
mod generate_rules_table;
mod print_ast;
mod print_cst;
mod print_tokens;
mod round_trip;
const ROOT_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../../");
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
struct Args {
#[command(subcommand)]
command: Command,
#[clap(flatten)]
global_options: GlobalConfigArgs,
}
#[derive(Subcommand)]
#[allow(clippy::large_enum_variant)]
enum Command {
/// Run all code and documentation generation steps.
GenerateAll(generate_all::Args),
/// Generate JSON schema for the TOML configuration file.
GenerateJSONSchema(generate_json_schema::Args),
/// Generate JSON schema for the Red Knot TOML configuration file.
GenerateKnotSchema(generate_knot_schema::Args),
/// Generate a Markdown-compatible table of supported lint rules.
GenerateRulesTable,
/// Generate a Markdown-compatible listing of configuration options.
GenerateOptions,
/// Generate CLI help.
GenerateCliHelp(generate_cli_help::Args),
/// Generate Markdown docs.
GenerateDocs(generate_docs::Args),
/// Print the AST for a given Python file.
PrintAST(print_ast::Args),
/// Print the LibCST CST for a given Python file.
PrintCST(print_cst::Args),
/// Print the token stream for a given Python file.
PrintTokens(print_tokens::Args),
/// Run round-trip source code generation on a given Python file.
RoundTrip(round_trip::Args),
/// Run a ruff command n times for profiling/benchmarking
Repeat {
#[clap(flatten)]
args: ruff::args::CheckCommand,
/// Run this many times
#[clap(long)]
repeat: usize,
},
/// Several utils related to the formatter which can be run on one or more repositories. The
/// selected set of files in a repository is the same as for `ruff check`.
///
/// * Check formatter stability: Format a repository twice and ensure that it looks that the
/// first and second formatting look the same.
/// * Format: Format the files in a repository to be able to check them with `git diff`
/// * Statistics: The subcommand the Jaccard index between the (assumed to be black formatted)
/// input and the ruff formatted output
FormatDev(format_dev::Args),
}
fn main() -> Result<ExitCode> {
let Args {
command,
global_options,
} = Args::parse();
#[allow(clippy::print_stdout)]
match command {
Command::GenerateAll(args) => generate_all::main(&args)?,
Command::GenerateJSONSchema(args) => generate_json_schema::main(&args)?,
Command::GenerateKnotSchema(args) => generate_knot_schema::main(&args)?,
Command::GenerateRulesTable => println!("{}", generate_rules_table::generate()),
Command::GenerateOptions => println!("{}", generate_options::generate()),
Command::GenerateCliHelp(args) => generate_cli_help::main(&args)?,
Command::GenerateDocs(args) => generate_docs::main(&args)?,
Command::PrintAST(args) => print_ast::main(&args)?,
Command::PrintCST(args) => print_cst::main(&args)?,
Command::PrintTokens(args) => print_tokens::main(&args)?,
Command::RoundTrip(args) => round_trip::main(&args)?,
Command::Repeat {
args: subcommand_args,
repeat,
} => {
set_up_logging(global_options.log_level())?;
for _ in 0..repeat {
check(subcommand_args.clone(), global_options.clone())?;
}
}
Command::FormatDev(args) => {
let exit_code = format_dev::main(&args)?;
return Ok(exit_code);
}
}
Ok(ExitCode::SUCCESS)
}