2022-07-15 17:06:18 +01:00
//! Configuration options for zls.
const Config = @This ( ) ;
const std = @import ( " std " ) ;
const setup = @import ( " setup.zig " ) ;
const known_folders = @import ( " known-folders " ) ;
const logger = std . log . scoped ( . config ) ;
2020-05-09 14:43:51 +01:00
2020-05-09 20:42:35 +01:00
/// Whether to enable snippet completions
2020-05-19 20:09:00 +01:00
enable_snippets : bool = false ,
2020-05-14 00:10:41 +01:00
2022-07-08 09:13:46 +01:00
/// Whether to enable unused variable warnings
enable_unused_variable_warnings : bool = false ,
2022-07-09 10:22:02 +01:00
/// Whether to enable import/embedFile argument completions (NOTE: these are triggered manually as updating the autotrigger characters may cause issues)
enable_import_embedfile_argument_completions : bool = false ,
2022-07-11 14:45:31 +01:00
/// Zig library path
2020-05-14 02:54:05 +01:00
zig_lib_path : ? [ ] const u8 = null ,
2020-05-15 20:10:53 +01:00
2022-07-11 14:45:31 +01:00
/// Zig executable path used to run the custom build runner.
2020-05-30 21:36:18 +01:00
/// May be used to find a lib path if none is provided.
zig_exe_path : ? [ ] const u8 = null ,
2020-05-15 20:10:53 +01:00
/// Whether to pay attention to style issues. This is opt-in since the style
/// guide explicitly states that the style info provided is a guideline only.
warn_style : bool = false ,
2020-05-25 18:04:23 +01:00
2021-01-12 11:10:51 +00:00
/// Path to the build_runner.zig file.
2020-05-25 18:04:23 +01:00
build_runner_path : ? [ ] const u8 = null ,
2020-06-16 12:27:00 +01:00
2021-03-27 19:37:51 +00:00
/// Path to a directory that will be used as cache when `zig run`ning the build runner
2021-01-12 11:10:51 +00:00
build_runner_cache_path : ? [ ] const u8 = null ,
2020-06-16 12:27:00 +01:00
/// Semantic token support
2020-11-15 22:07:35 +00:00
enable_semantic_tokens : bool = true ,
2020-07-07 21:26:12 +01:00
/// Whether to enable `*` and `?` operators in completion lists
operator_completions : bool = true ,
2021-03-06 19:55:59 +00:00
2021-03-26 09:20:20 +00:00
/// Whether the @ sign should be part of the completion of builtins
include_at_in_builtins : bool = false ,
2021-03-27 19:37:51 +00:00
/// The detail field of completions is truncated to be no longer than this (in bytes).
2022-07-11 14:45:31 +01:00
max_detail_length : usize = 1048576 ,
2021-03-27 19:37:51 +00:00
2021-03-06 19:55:59 +00:00
/// Skips references to std. This will improve lookup speeds.
/// Going to definition however will continue to work
2021-03-07 13:51:47 +00:00
skip_std_references : bool = false ,
2021-12-30 03:35:16 +00:00
2022-07-11 14:45:31 +01:00
/// Path to "builtin;" useful for debugging, automatically set if let null
2021-12-30 03:35:16 +00:00
builtin_path : ? [ ] const u8 = null ,
2022-07-15 17:06:18 +01:00
pub fn configChanged ( config : * Config , allocator : std . mem . Allocator , builtin_creation_dir : ? [ ] const u8 ) ! void {
// Find the zig executable in PATH
find_zig : {
if ( config . zig_exe_path ) | exe_path | {
if ( std . fs . path . isAbsolute ( exe_path ) ) not_valid : {
std . fs . cwd ( ) . access ( exe_path , . { } ) catch break : not_valid ;
break : find_zig ;
}
logger . debug ( " zig path `{s}` is not absolute, will look in path " , . { exe_path } ) ;
allocator . free ( exe_path ) ;
}
config . zig_exe_path = try setup . findZig ( allocator ) ;
}
if ( config . zig_exe_path ) | exe_path | {
logger . info ( " Using zig executable {s} " , . { exe_path } ) ;
if ( config . zig_lib_path = = null ) find_lib_path : {
// Use `zig env` to find the lib path
const zig_env_result = try std . ChildProcess . exec ( . {
. allocator = allocator ,
. argv = & [ _ ] [ ] const u8 { exe_path , " env " } ,
} ) ;
defer {
allocator . free ( zig_env_result . stdout ) ;
allocator . free ( zig_env_result . stderr ) ;
}
switch ( zig_env_result . term ) {
. Exited = > | exit_code | {
if ( exit_code = = 0 ) {
const Env = struct {
zig_exe : [ ] const u8 ,
lib_dir : ? [ ] const u8 ,
std_dir : [ ] const u8 ,
global_cache_dir : [ ] const u8 ,
version : [ ] const u8 ,
} ;
var json_env = std . json . parse (
Env ,
& std . json . TokenStream . init ( zig_env_result . stdout ) ,
. { . allocator = allocator } ,
) catch {
logger . err ( " Failed to parse zig env JSON result " , . { } ) ;
break : find_lib_path ;
} ;
defer std . json . parseFree ( Env , json_env , . { . allocator = allocator } ) ;
// We know this is allocated with `allocator`, we just steal it!
config . zig_lib_path = json_env . lib_dir . ? ;
json_env . lib_dir = null ;
logger . info ( " Using zig lib path '{s}' " , . { config . zig_lib_path } ) ;
}
} ,
else = > logger . err ( " zig env invocation failed " , . { } ) ,
}
}
} else {
logger . warn ( " Zig executable path not specified in zls.json and could not be found in PATH " , . { } ) ;
}
if ( config . zig_lib_path = = null ) {
logger . warn ( " Zig standard library path not specified in zls.json and could not be resolved from the zig executable " , . { } ) ;
}
if ( config . builtin_path = = null and config . zig_exe_path ! = null and builtin_creation_dir ! = null ) blk : {
const result = try std . ChildProcess . exec ( . {
. allocator = allocator ,
. argv = & . {
config . zig_exe_path . ? ,
" build-exe " ,
" --show-builtin " ,
} ,
. max_output_bytes = 1024 * 1024 * 50 ,
} ) ;
defer allocator . free ( result . stdout ) ;
defer allocator . free ( result . stderr ) ;
var d = try std . fs . cwd ( ) . openDir ( builtin_creation_dir . ? , . { } ) ;
defer d . close ( ) ;
const f = d . createFile ( " builtin.zig " , . { } ) catch | err | switch ( err ) {
error . AccessDenied = > break : blk ,
else = > | e | return e ,
} ;
defer f . close ( ) ;
try f . writer ( ) . writeAll ( result . stdout ) ;
config . builtin_path = try std . fs . path . join ( allocator , & . { builtin_creation_dir . ? , " builtin.zig " } ) ;
}
config . build_runner_path = if ( config . build_runner_path ) | p |
try allocator . dupe ( u8 , p )
else blk : {
var exe_dir_bytes : [ std . fs . MAX_PATH_BYTES ] u8 = undefined ;
const exe_dir_path = try std . fs . selfExeDirPath ( & exe_dir_bytes ) ;
break : blk try std . fs . path . resolve ( allocator , & [ _ ] [ ] const u8 { exe_dir_path , " build_runner.zig " } ) ;
} ;
config . build_runner_cache_path = if ( config . build_runner_cache_path ) | p |
try allocator . dupe ( u8 , p )
else blk : {
const cache_dir_path = ( try known_folders . getPath ( allocator , . cache ) ) orelse {
logger . warn ( " Known-folders could not fetch the cache path " , . { } ) ;
return ;
} ;
defer allocator . free ( cache_dir_path ) ;
break : blk try std . fs . path . resolve ( allocator , & [ _ ] [ ] const u8 { cache_dir_path , " zls " } ) ;
} ;
}