1+ use std:: {
2+ env,
3+ path:: { Path , PathBuf } ,
4+ } ;
5+
16use lsp_types:: {
27 InitializeParams , ServerCapabilities , TextDocumentSyncCapability , TextDocumentSyncKind ,
38 TextDocumentSyncOptions ,
49} ;
10+ use tracing:: { error, info} ;
11+
12+ use crate :: workspace:: manifest:: ProjectManifest ;
13+
14+ /// The LSP config.
15+ ///
16+ /// This struct is internal only and should not be serialized or deserialized. Instead, values in
17+ /// this struct are the full view of all merged config sources, such as `initialization_opts`,
18+ /// on-disk config files (e.g. `foundry.toml`).
19+ #[ derive( Default , Clone ) ]
20+ pub ( crate ) struct Config {
21+ root_path : PathBuf ,
22+ workspace_roots : Vec < PathBuf > ,
23+ discovered_projects : Vec < ProjectManifest > ,
24+ }
25+
26+ impl Config {
27+ pub ( crate ) fn new ( root_path : PathBuf , workspace_roots : Vec < PathBuf > ) -> Self {
28+ Config { root_path, workspace_roots, discovered_projects : Default :: default ( ) }
29+ }
30+
31+ pub ( crate ) fn rediscover_workspaces ( & mut self ) {
32+ let discovered = ProjectManifest :: discover_all ( & self . workspace_roots ) ;
33+ info ! ( "discovered projects: {:?}" , discovered) ;
34+ if discovered. is_empty ( ) {
35+ error ! ( "failed to find any projects in {:?}" , & self . workspace_roots) ;
36+ }
37+ self . discovered_projects = discovered;
38+ }
39+
40+ pub ( crate ) fn remove_workspace ( & mut self , path : & PathBuf ) {
41+ if let Some ( pos) = self . workspace_roots . iter ( ) . position ( |it| it == path) {
42+ self . workspace_roots . remove ( pos) ;
43+ }
44+ }
45+
46+ pub ( crate ) fn add_workspaces ( & mut self , paths : impl Iterator < Item = PathBuf > ) {
47+ self . workspace_roots . extend ( paths) ;
48+ }
49+
50+ pub ( crate ) fn root_path ( & self ) -> & Path {
51+ self . root_path . as_path ( )
52+ }
53+ }
54+
55+ pub ( crate ) fn negotiate_capabilities ( params : InitializeParams ) -> ( ServerCapabilities , Config ) {
56+ // todo: make this absolute guaranteed
57+ #[ allow( deprecated) ]
58+ let root_path = match params. root_uri . and_then ( |it| it. to_file_path ( ) . ok ( ) ) {
59+ Some ( it) => it,
60+ None => {
61+ // todo: unwrap
62+ env:: current_dir ( ) . unwrap ( )
63+ }
64+ } ;
565
6- #[ derive( Default ) ]
7- pub ( crate ) struct Config { }
66+ // todo: make this absolute guaranteed
67+ // The latest LSP spec mandates clients report `workspace_folders`, but some might still report
68+ // `root_uri`.
69+ let workspace_roots = params
70+ . workspace_folders
71+ . map ( |workspaces| {
72+ workspaces. into_iter ( ) . filter_map ( |it| it. uri . to_file_path ( ) . ok ( ) ) . collect :: < Vec < _ > > ( )
73+ } )
74+ . filter ( |workspaces| !workspaces. is_empty ( ) )
75+ . unwrap_or_else ( || vec ! [ root_path. clone( ) ] ) ;
876
9- pub ( crate ) fn negotiate_capabilities ( _: InitializeParams ) -> ( ServerCapabilities , Config ) {
1077 (
1178 ServerCapabilities {
1279 text_document_sync : Some ( TextDocumentSyncCapability :: Options (
@@ -20,6 +87,6 @@ pub(crate) fn negotiate_capabilities(_: InitializeParams) -> (ServerCapabilities
2087 ) ) ,
2188 ..Default :: default ( )
2289 } ,
23- Config :: default ( ) ,
90+ Config :: new ( root_path , workspace_roots ) ,
2491 )
2592}
0 commit comments