@@ -3,8 +3,11 @@ use std::{ops::Deref, path::PathBuf, str::FromStr};
33use lsp_types:: Url ;
44use rustc_hash:: FxHashMap ;
55use serde:: Deserialize ;
6+ use serde_json:: { Map , Value } ;
7+ use thiserror:: Error ;
68
79use ruff_linter:: { line_width:: LineLength , RuleSelector } ;
10+ use ruff_workspace:: options:: Options ;
811
912/// Maps a workspace URI to its associated client settings. Used during server initialization.
1013pub ( crate ) type WorkspaceSettingsMap = FxHashMap < Url , ClientSettings > ;
@@ -31,7 +34,7 @@ pub(crate) struct ResolvedClientSettings {
3134#[ derive( Clone , Debug ) ]
3235#[ cfg_attr( test, derive( PartialEq , Eq ) ) ]
3336pub ( crate ) struct ResolvedEditorSettings {
34- pub ( super ) configuration : Option < PathBuf > ,
37+ pub ( super ) configuration : Option < ResolvedConfiguration > ,
3538 pub ( super ) lint_preview : Option < bool > ,
3639 pub ( super ) format_preview : Option < bool > ,
3740 pub ( super ) select : Option < Vec < RuleSelector > > ,
@@ -42,6 +45,38 @@ pub(crate) struct ResolvedEditorSettings {
4245 pub ( super ) configuration_preference : ConfigurationPreference ,
4346}
4447
48+ #[ derive( Clone , Debug ) ]
49+ #[ cfg_attr( test, derive( PartialEq , Eq ) ) ]
50+ pub ( crate ) enum ResolvedConfiguration {
51+ FilePath ( PathBuf ) ,
52+ SettingsOverride ( Options ) ,
53+ }
54+
55+ impl TryFrom < & ClientConfiguration > for ResolvedConfiguration {
56+ type Error = ResolvedConfigurationError ;
57+
58+ fn try_from ( value : & ClientConfiguration ) -> Result < Self , Self :: Error > {
59+ match value {
60+ ClientConfiguration :: String ( path) => Ok ( ResolvedConfiguration :: FilePath (
61+ PathBuf :: from ( shellexpand:: full ( path) ?. as_ref ( ) ) ,
62+ ) ) ,
63+ ClientConfiguration :: Object ( map) => Ok ( ResolvedConfiguration :: SettingsOverride (
64+ toml:: Table :: try_from ( map) ?. try_into :: < Options > ( ) ?,
65+ ) ) ,
66+ }
67+ }
68+ }
69+
70+ #[ derive( Debug , Error ) ]
71+ pub ( crate ) enum ResolvedConfigurationError {
72+ #[ error( transparent) ]
73+ ShellExpand ( #[ from] shellexpand:: LookupError < std:: env:: VarError > ) ,
74+ #[ error( transparent) ]
75+ InvalidToml ( #[ from] toml:: ser:: Error ) ,
76+ #[ error( transparent) ]
77+ InvalidRuffSchema ( #[ from] toml:: de:: Error ) ,
78+ }
79+
4580/// Determines how multiple conflicting configurations should be resolved - in this
4681/// case, the configuration from the client settings and configuration from local
4782/// `.toml` files (aka 'workspace' configuration).
@@ -57,12 +92,20 @@ pub(crate) enum ConfigurationPreference {
5792 EditorOnly ,
5893}
5994
95+ #[ derive( Debug , Deserialize ) ]
96+ #[ cfg_attr( test, derive( PartialEq , Eq ) ) ]
97+ #[ serde( untagged) ]
98+ enum ClientConfiguration {
99+ String ( String ) ,
100+ Object ( Map < String , Value > ) ,
101+ }
102+
60103/// This is a direct representation of the settings schema sent by the client.
61104#[ derive( Debug , Deserialize , Default ) ]
62105#[ cfg_attr( test, derive( PartialEq , Eq ) ) ]
63106#[ serde( rename_all = "camelCase" ) ]
64107pub struct ClientSettings {
65- configuration : Option < String > ,
108+ configuration : Option < ClientConfiguration > ,
66109 fix_all : Option < bool > ,
67110 organize_imports : Option < bool > ,
68111 lint : Option < LintOptions > ,
@@ -306,11 +349,15 @@ impl ResolvedClientSettings {
306349 ) ,
307350 editor_settings : ResolvedEditorSettings {
308351 configuration : Self :: resolve_optional ( all_settings, |settings| {
309- settings
310- . configuration
311- . as_ref ( )
312- . and_then ( |config_path| shellexpand:: full ( config_path) . ok ( ) )
313- . map ( |config_path| PathBuf :: from ( config_path. as_ref ( ) ) )
352+ settings. configuration . as_ref ( ) . and_then ( |configuration| {
353+ match ResolvedConfiguration :: try_from ( configuration) {
354+ Ok ( configuration) => Some ( configuration) ,
355+ Err ( err) => {
356+ tracing:: error!( "Failed to resolve configuration: {err}" ) ;
357+ None
358+ }
359+ }
360+ } )
314361 } ) ,
315362 lint_preview : Self :: resolve_optional ( all_settings, |settings| {
316363 settings. lint . as_ref ( ) ?. preview
0 commit comments