## Summary This PR adds support for configuring Red Knot in the `tool.knot` section of the project's `pyproject.toml` section. Options specified on the CLI precede the options in the configuration file. This PR only supports the `environment` and the `src.root` options for now. Other options will be added as separate PRs. There are also a few concerns that I intentionally ignored as part of this PR: * Handling of relative paths: We need to anchor paths relative to the current working directory (CLI), or the project (`pyproject.toml` or `knot.toml`) * Tracking the source of a value. Diagnostics would benefit from knowing from which configuration a value comes so that we can point the user to the right configuration file (or CLI) if the configuration is invalid. * Schema generation and there's a lot more; see https://github.com/astral-sh/ruff/issues/15491 This PR changes the default for first party codes: Our existing default was to only add the project root. Now, Red Knot adds the project root and `src` (if such a directory exists). Theoretically, we'd have to add a file watcher event that changes the first-party search paths if a user later creates a `src` directory. I think this is pretty uncommon, which is why I ignored the complexity for now but I can be persuaded to handle it if it's considered important. Part of https://github.com/astral-sh/ruff/issues/15491 ## Test Plan Existing tests, new file watching test demonstrating that changing the python version and platform is correctly reflected.
110 lines
2.7 KiB
Rust
110 lines
2.7 KiB
Rust
use red_knot_python_semantic::lint::{LintRegistry, RuleSelection};
|
|
use red_knot_python_semantic::{
|
|
default_lint_registry, Db as SemanticDb, Program, ProgramSettings, PythonPlatform,
|
|
PythonVersion, SearchPathSettings,
|
|
};
|
|
use ruff_db::files::{File, Files};
|
|
use ruff_db::system::{DbWithTestSystem, System, SystemPath, SystemPathBuf, TestSystem};
|
|
use ruff_db::vendored::VendoredFileSystem;
|
|
use ruff_db::{Db as SourceDb, Upcast};
|
|
|
|
#[salsa::db]
|
|
#[derive(Clone)]
|
|
pub(crate) struct Db {
|
|
project_root: SystemPathBuf,
|
|
storage: salsa::Storage<Self>,
|
|
files: Files,
|
|
system: TestSystem,
|
|
vendored: VendoredFileSystem,
|
|
rule_selection: RuleSelection,
|
|
}
|
|
|
|
impl Db {
|
|
pub(crate) fn setup(project_root: SystemPathBuf) -> Self {
|
|
let rule_selection = RuleSelection::from_registry(default_lint_registry());
|
|
|
|
let db = Self {
|
|
project_root,
|
|
storage: salsa::Storage::default(),
|
|
system: TestSystem::default(),
|
|
vendored: red_knot_vendored::file_system().clone(),
|
|
files: Files::default(),
|
|
rule_selection,
|
|
};
|
|
|
|
db.memory_file_system()
|
|
.create_directory_all(&db.project_root)
|
|
.unwrap();
|
|
|
|
Program::from_settings(
|
|
&db,
|
|
ProgramSettings {
|
|
python_version: PythonVersion::default(),
|
|
python_platform: PythonPlatform::default(),
|
|
search_paths: SearchPathSettings::new(vec![db.project_root.clone()]),
|
|
},
|
|
)
|
|
.expect("Invalid search path settings");
|
|
|
|
db
|
|
}
|
|
|
|
pub(crate) fn project_root(&self) -> &SystemPath {
|
|
&self.project_root
|
|
}
|
|
}
|
|
|
|
impl DbWithTestSystem for Db {
|
|
fn test_system(&self) -> &TestSystem {
|
|
&self.system
|
|
}
|
|
|
|
fn test_system_mut(&mut self) -> &mut TestSystem {
|
|
&mut self.system
|
|
}
|
|
}
|
|
|
|
#[salsa::db]
|
|
impl SourceDb for Db {
|
|
fn vendored(&self) -> &VendoredFileSystem {
|
|
&self.vendored
|
|
}
|
|
|
|
fn system(&self) -> &dyn System {
|
|
&self.system
|
|
}
|
|
|
|
fn files(&self) -> &Files {
|
|
&self.files
|
|
}
|
|
}
|
|
|
|
impl Upcast<dyn SourceDb> for Db {
|
|
fn upcast(&self) -> &(dyn SourceDb + 'static) {
|
|
self
|
|
}
|
|
fn upcast_mut(&mut self) -> &mut (dyn SourceDb + 'static) {
|
|
self
|
|
}
|
|
}
|
|
|
|
#[salsa::db]
|
|
impl SemanticDb for Db {
|
|
fn is_file_open(&self, file: File) -> bool {
|
|
!file.path(self).is_vendored_path()
|
|
}
|
|
|
|
fn rule_selection(&self) -> &RuleSelection {
|
|
&self.rule_selection
|
|
}
|
|
|
|
fn lint_registry(&self) -> &LintRegistry {
|
|
default_lint_registry()
|
|
}
|
|
}
|
|
|
|
#[salsa::db]
|
|
impl salsa::Database for Db {
|
|
fn salsa_event(&self, _event: &dyn Fn() -> salsa::Event) {}
|
|
}
|