33use crate :: metadata:: options:: OptionDiagnostic ;
44pub use db:: { Db , ProjectDatabase } ;
55use files:: { Index , Indexed , IndexedFiles } ;
6+ use metadata:: settings:: Settings ;
67pub use metadata:: { ProjectDiscoveryError , ProjectMetadata } ;
78use red_knot_python_semantic:: lint:: { LintRegistry , LintRegistryBuilder , RuleSelection } ;
89use red_knot_python_semantic:: register_lints;
@@ -66,12 +67,22 @@ pub struct Project {
6667 /// The metadata describing the project, including the unresolved options.
6768 #[ return_ref]
6869 pub metadata : ProjectMetadata ,
70+
71+ /// The resolved project settings.
72+ #[ return_ref]
73+ pub settings : Settings ,
74+
75+ /// Diagnostics that were generated when resolving the project settings.
76+ #[ return_ref]
77+ settings_diagnostics : Vec < OptionDiagnostic > ,
6978}
7079
7180#[ salsa:: tracked]
7281impl Project {
7382 pub fn from_metadata ( db : & dyn Db , metadata : ProjectMetadata ) -> Self {
74- Project :: builder ( metadata)
83+ let ( settings, settings_diagnostics) = metadata. options ( ) . to_settings ( db) ;
84+
85+ Project :: builder ( metadata, settings, settings_diagnostics)
7586 . durability ( Durability :: MEDIUM )
7687 . open_fileset_durability ( Durability :: LOW )
7788 . file_set_durability ( Durability :: LOW )
@@ -86,30 +97,37 @@ impl Project {
8697 self . metadata ( db) . name ( )
8798 }
8899
100+ /// Returns the resolved linter rules for the project.
101+ ///
102+ /// This is a salsa query to prevent re-computing queries if other, unrelated
103+ /// settings change. For example, we don't want that changing the terminal settings
104+ /// invalidates any type checking queries.
105+ #[ salsa:: tracked]
106+ pub fn rules ( self , db : & dyn Db ) -> Arc < RuleSelection > {
107+ self . settings ( db) . to_rules ( )
108+ }
109+
89110 pub fn reload ( self , db : & mut dyn Db , metadata : ProjectMetadata ) {
90111 tracing:: debug!( "Reloading project" ) ;
91112 assert_eq ! ( self . root( db) , metadata. root( ) ) ;
92113
93114 if & metadata != self . metadata ( db) {
115+ let ( settings, settings_diagnostics) = metadata. options ( ) . to_settings ( db) ;
116+
117+ if self . settings ( db) != & settings {
118+ self . set_settings ( db) . to ( settings) ;
119+ }
120+
121+ if self . settings_diagnostics ( db) != & settings_diagnostics {
122+ self . set_settings_diagnostics ( db) . to ( settings_diagnostics) ;
123+ }
124+
94125 self . set_metadata ( db) . to ( metadata) ;
95126 }
96127
97128 self . reload_files ( db) ;
98129 }
99130
100- pub fn rule_selection ( self , db : & dyn Db ) -> & RuleSelection {
101- let ( selection, _) = self . rule_selection_with_diagnostics ( db) ;
102- selection
103- }
104-
105- #[ salsa:: tracked( return_ref) ]
106- fn rule_selection_with_diagnostics (
107- self ,
108- db : & dyn Db ,
109- ) -> ( RuleSelection , Vec < OptionDiagnostic > ) {
110- self . metadata ( db) . options ( ) . to_rule_selection ( db)
111- }
112-
113131 /// Checks all open files in the project and its dependencies.
114132 pub ( crate ) fn check ( self , db : & ProjectDatabase ) -> Vec < Box < dyn Diagnostic > > {
115133 let project_span = tracing:: debug_span!( "Project::check" ) ;
@@ -118,8 +136,7 @@ impl Project {
118136 tracing:: debug!( "Checking project '{name}'" , name = self . name( db) ) ;
119137
120138 let mut diagnostics: Vec < Box < dyn Diagnostic > > = Vec :: new ( ) ;
121- let ( _, options_diagnostics) = self . rule_selection_with_diagnostics ( db) ;
122- diagnostics. extend ( options_diagnostics. iter ( ) . map ( |diagnostic| {
139+ diagnostics. extend ( self . settings_diagnostics ( db) . iter ( ) . map ( |diagnostic| {
123140 let diagnostic: Box < dyn Diagnostic > = Box :: new ( diagnostic. clone ( ) ) ;
124141 diagnostic
125142 } ) ) ;
@@ -151,9 +168,8 @@ impl Project {
151168 }
152169
153170 pub ( crate ) fn check_file ( self , db : & dyn Db , file : File ) -> Vec < Box < dyn Diagnostic > > {
154- let ( _, options_diagnostics) = self . rule_selection_with_diagnostics ( db) ;
155-
156- let mut file_diagnostics: Vec < _ > = options_diagnostics
171+ let mut file_diagnostics: Vec < _ > = self
172+ . settings_diagnostics ( db)
157173 . iter ( )
158174 . map ( |diagnostic| {
159175 let diagnostic: Box < dyn Diagnostic > = Box :: new ( diagnostic. clone ( ) ) ;
0 commit comments