@@ -12,6 +12,7 @@ use std::collections::HashMap;
1212use vhdl_lang:: ast:: { Designator , ObjectClass } ;
1313
1414use crate :: rpc_channel:: SharedRpcChannel ;
15+ use serde_json:: Value ;
1516use std:: io;
1617use std:: io:: ErrorKind ;
1718use std:: path:: { Path , PathBuf } ;
@@ -21,10 +22,33 @@ use vhdl_lang::{
2122 Source , SrcPos , Token , Type , VHDLStandard ,
2223} ;
2324
25+ /// Defines how the language server handles files
26+ /// that are not part of the `vhdl_ls.toml` project settings file.
27+ #[ derive( Default , Clone , Eq , PartialEq ) ]
28+ pub enum NonProjectFileHandling {
29+ /// Ignore any non-project files
30+ Ignore ,
31+ /// Add non-project files to an anonymous library and analyze them
32+ #[ default]
33+ Analyze ,
34+ }
35+
36+ impl NonProjectFileHandling {
37+ pub fn from_string ( value : & str ) -> Option < NonProjectFileHandling > {
38+ use NonProjectFileHandling :: * ;
39+ Some ( match value {
40+ "ignore" => Ignore ,
41+ "analyze" => Analyze ,
42+ _ => return None ,
43+ } )
44+ }
45+ }
46+
2447#[ derive( Default , Clone ) ]
2548pub struct VHDLServerSettings {
2649 pub no_lint : bool ,
2750 pub silent : bool ,
51+ pub non_project_file_handling : NonProjectFileHandling ,
2852}
2953
3054pub struct VHDLServer {
@@ -116,12 +140,30 @@ impl VHDLServer {
116140 config
117141 }
118142
143+ fn apply_initial_options ( & mut self , options : & Value ) {
144+ let Some ( non_project_file_handling) = options. get ( "nonProjectFiles" ) else {
145+ return ;
146+ } ;
147+ match non_project_file_handling {
148+ Value :: String ( handling) => match NonProjectFileHandling :: from_string ( handling) {
149+ None => self . message ( Message :: error ( format ! (
150+ "Illegal setting {handling} for nonProjectFiles setting"
151+ ) ) ) ,
152+ Some ( handling) => self . settings . non_project_file_handling = handling,
153+ } ,
154+ _ => self . message ( Message :: error ( "nonProjectFiles must be a string" ) ) ,
155+ }
156+ }
157+
119158 pub fn initialize_request ( & mut self , init_params : InitializeParams ) -> InitializeResult {
120159 self . config_file = self . root_uri_config_file ( & init_params) ;
121160 let config = self . load_config ( ) ;
122161 self . severity_map = * config. severities ( ) ;
123162 self . project = Project :: from_config ( config, & mut self . message_filter ( ) ) ;
124163 self . project . enable_unused_declaration_detection ( ) ;
164+ if let Some ( options) = & init_params. initialization_options {
165+ self . apply_initial_options ( options)
166+ }
125167 self . init_params = Some ( init_params) ;
126168 let trigger_chars: Vec < String > = r"." . chars ( ) . map ( |ch| ch. to_string ( ) ) . collect ( ) ;
127169
@@ -228,7 +270,7 @@ impl VHDLServer {
228270 }
229271 self . project . update_source ( & source) ;
230272 self . publish_diagnostics ( ) ;
231- } else {
273+ } else if self . settings . non_project_file_handling != NonProjectFileHandling :: Ignore {
232274 self . message ( Message :: error ( format ! (
233275 "Changing file {} that is not part of the project" ,
234276 file_name. to_string_lossy( )
@@ -244,13 +286,18 @@ impl VHDLServer {
244286 self . project . update_source ( & source) ;
245287 self . publish_diagnostics ( ) ;
246288 } else {
247- self . message ( Message :: warning ( format ! (
248- "Opening file {} that is not part of the project" ,
249- file_name. to_string_lossy( )
250- ) ) ) ;
251- self . project
252- . update_source ( & Source :: inline ( & file_name, text) ) ;
253- self . publish_diagnostics ( ) ;
289+ match self . settings . non_project_file_handling {
290+ NonProjectFileHandling :: Ignore => { }
291+ NonProjectFileHandling :: Analyze => {
292+ self . message ( Message :: warning ( format ! (
293+ "Opening file {} that is not part of the project" ,
294+ file_name. to_string_lossy( )
295+ ) ) ) ;
296+ self . project
297+ . update_source ( & Source :: inline ( & file_name, text) ) ;
298+ self . publish_diagnostics ( ) ;
299+ }
300+ }
254301 }
255302 }
256303
0 commit comments