-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added project-specific Zed IDE settings #127793
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ Session.vim | |
.idea | ||
*.iml | ||
.vscode | ||
.zed | ||
.project | ||
.favorites.json | ||
.settings/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,10 +34,10 @@ pub enum Profile { | |
|
||
static PROFILE_DIR: &str = "src/bootstrap/defaults"; | ||
|
||
/// A list of historical hashes of `src/etc/rust_analyzer_settings.json`. | ||
/// New entries should be appended whenever this is updated so we can detect | ||
/// A list of historical SHA-256 hashes of `src/etc/vscode_settings.json`. New | ||
/// entries should be appended whenever this is updated so we can detect | ||
/// outdated vs. user-modified settings files. | ||
static SETTINGS_HASHES: &[&str] = &[ | ||
static VSCODE_SETTINGS_HASHES: &[&str] = &[ | ||
"ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8", | ||
"56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922", | ||
"af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0", | ||
|
@@ -46,7 +46,14 @@ static SETTINGS_HASHES: &[&str] = &[ | |
"b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a", | ||
"828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000", | ||
]; | ||
static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json"); | ||
static VSCODE_SETTINGS: &str = include_str!("../../../../etc/vscode_settings.json"); | ||
|
||
/// A list of historical SHA-256 hashes of `src/etc/zed_settings.json`. New | ||
/// entries should be appended whenever this is updated so we can detect | ||
/// outdated vs. user-modified settings files. | ||
static ZED_SETTINGS_HASHES: &[&str] = | ||
&["08bb47a0a93947284102eece102cb2e21a91ff952bf21798df92590e31240d98"]; | ||
static ZED_SETTINGS: &str = include_str!("../../../../etc/zed_settings.json"); | ||
|
||
impl Profile { | ||
fn include_path(&self, src_path: &Path) -> PathBuf { | ||
|
@@ -527,11 +534,11 @@ undesirable, simply delete the `pre-push` file from .git/hooks." | |
Ok(()) | ||
} | ||
|
||
/// Sets up or displays `src/etc/rust_analyzer_settings.json` | ||
/// Sets up or displays `src/etc/vscode_settings.json` | ||
#[derive(Clone, Debug, Eq, PartialEq, Hash)] | ||
pub struct Vscode; | ||
pub struct VsCode; | ||
|
||
impl Step for Vscode { | ||
impl Step for VsCode { | ||
type Output = (); | ||
const DEFAULT: bool = true; | ||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { | ||
|
@@ -543,7 +550,7 @@ impl Step for Vscode { | |
} | ||
if let [cmd] = &run.paths[..] { | ||
if cmd.assert_single_path().path.as_path().as_os_str() == "vscode" { | ||
run.builder.ensure(Vscode); | ||
run.builder.ensure(VsCode); | ||
} | ||
} | ||
} | ||
|
@@ -559,7 +566,7 @@ impl Step for Vscode { | |
/// Create a `.vscode/settings.json` file for rustc development, or just print it | ||
/// If this method should be re-called, it returns `false`. | ||
fn create_vscode_settings_maybe(config: &Config) -> io::Result<bool> { | ||
let (current_hash, historical_hashes) = SETTINGS_HASHES.split_last().unwrap(); | ||
let (current_hash, historical_hashes) = VSCODE_SETTINGS_HASHES.split_last().unwrap(); | ||
let vscode_settings = config.src.join(".vscode").join("settings.json"); | ||
// If None, no settings.json exists | ||
// If Some(true), is a previous version of settings.json | ||
|
@@ -619,10 +626,110 @@ fn create_vscode_settings_maybe(config: &Config) -> io::Result<bool> { | |
} | ||
_ => "Created", | ||
}; | ||
fs::write(&vscode_settings, RUST_ANALYZER_SETTINGS)?; | ||
fs::write(&vscode_settings, VSCODE_SETTINGS)?; | ||
println!("{verb} `.vscode/settings.json`"); | ||
} else { | ||
println!("\n{RUST_ANALYZER_SETTINGS}"); | ||
println!("\n{VSCODE_SETTINGS}"); | ||
} | ||
Ok(should_create) | ||
} | ||
|
||
/// Sets up or displays `src/etc/zed_settings.json` | ||
#[derive(Clone, Debug, Eq, PartialEq, Hash)] | ||
pub struct Zed; | ||
|
||
impl Step for Zed { | ||
type Output = (); | ||
const DEFAULT: bool = true; | ||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { | ||
run.alias("zed") | ||
} | ||
fn make_run(run: RunConfig<'_>) { | ||
if run.builder.config.dry_run() { | ||
return; | ||
} | ||
if let [cmd] = &run.paths[..] { | ||
if cmd.assert_single_path().path.as_path().as_os_str() == "zed" { | ||
run.builder.ensure(Zed); | ||
} | ||
} | ||
} | ||
fn run(self, builder: &Builder<'_>) -> Self::Output { | ||
let config = &builder.config; | ||
if config.dry_run() { | ||
return; | ||
} | ||
while !t!(create_zed_settings_maybe(config)) {} | ||
} | ||
} | ||
|
||
/// Create a `.zed/settings.json` file for rustc development, or just print it | ||
/// If this method should be re-called, it returns `false`. | ||
fn create_zed_settings_maybe(config: &Config) -> io::Result<bool> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this function be deduplicated with the vscode version? |
||
let (current_hash, historical_hashes) = ZED_SETTINGS_HASHES.split_last().unwrap(); | ||
let zed_settings = config.src.join(".zed").join("settings.json"); | ||
// If None, no settings.json exists | ||
// If Some(true), is a previous version of settings.json | ||
// If Some(false), is not a previous version (i.e. user modified) | ||
// If it's up to date we can just skip this | ||
let mut mismatched_settings = None; | ||
if let Ok(current) = fs::read_to_string(&zed_settings) { | ||
let mut hasher = sha2::Sha256::new(); | ||
hasher.update(¤t); | ||
let hash = hex_encode(hasher.finalize().as_slice()); | ||
if hash == *current_hash { | ||
return Ok(true); | ||
} else if historical_hashes.contains(&hash.as_str()) { | ||
mismatched_settings = Some(true); | ||
} else { | ||
mismatched_settings = Some(false); | ||
} | ||
} | ||
println!( | ||
"\nx.py can automatically install the recommended `.zed/settings.json` file for rustc development" | ||
); | ||
match mismatched_settings { | ||
Some(true) => eprintln!( | ||
"WARNING: existing `.zed/settings.json` is out of date, x.py will update it" | ||
), | ||
Some(false) => eprintln!( | ||
"WARNING: existing `.zed/settings.json` has been modified by user, x.py will back it up and replace it" | ||
), | ||
_ => (), | ||
} | ||
let should_create = match prompt_user( | ||
"Would you like to create/update settings.json? (Press 'p' to preview values): [y/N]", | ||
)? { | ||
Some(PromptResult::Yes) => true, | ||
Some(PromptResult::Print) => false, | ||
_ => { | ||
println!("Ok, skipping settings!"); | ||
return Ok(true); | ||
} | ||
}; | ||
if should_create { | ||
let path = config.src.join(".zed"); | ||
if !path.exists() { | ||
fs::create_dir(&path)?; | ||
} | ||
let verb = match mismatched_settings { | ||
// exists but outdated, we can replace this | ||
Some(true) => "Updated", | ||
// exists but user modified, back it up | ||
Some(false) => { | ||
// exists and is not current version or outdated, so back it up | ||
let mut backup = zed_settings.clone(); | ||
backup.set_extension("json.bak"); | ||
eprintln!("WARNING: copying `settings.json` to `settings.json.bak`"); | ||
fs::copy(&zed_settings, &backup)?; | ||
"Updated" | ||
} | ||
_ => "Created", | ||
}; | ||
fs::write(&zed_settings, ZED_SETTINGS)?; | ||
println!("{verb} `.zed/settings.json`"); | ||
} else { | ||
println!("\n{ZED_SETTINGS}"); | ||
} | ||
Ok(should_create) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
{ | ||
// The following commented-out VS Code settings are not supported by Zed yet. | ||
// "git.detectSubmodulesLimit": 20 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This option was introduced for vscode in #120138. There is a fair chance that zed won't suffer from the same issue once it has a git ui anyway (they may not even add a hard limit on the amount of auto detected git submodules at all). I don't think there is any value in keeping this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It could be nicer to still keep one file for RA settings, then just delete this key via bootstrap (serde_json is already a dependency). So if there are future updates that work for both, they only need to happen in one file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In order to do this properly, I think we'll need three files: one shared file for Even IDE settings that do the same thing are different between the two IDEs. For example, to turn on format-on-save, VS Code wants There are also JSON structure requirements that differ between the IDEs. For example, VS Code wants the {
"rust-analyzer.rustc.source": "discover"
} Zed wants the {
"lsp": {
"rust-analyzer": {
"initialization_options": {
"rustc": {
"source": "discover"
}
}
}
}
} So this means that we need to do JSON parsing of our three files, transformation of the structure, and JSON generation of the resulting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could also just have one rust source file with everything in use serde_json::{json, Value};
fn base_settings() -> Value {
json! {{
// common settings
}}
}
fn vscode_settings() -> Value {
let vscode_specific = json! {{ anything new}}
let mut inner = base_settings();
inner.as_object_mut().unwrap().extend(vscode_specific);
json! {{
"lsp": {
"rust_analyzer": /* other nesting */ inner,
}
}}
}
fn zed_settings() -> Value {
// ...
} Which would also be kind of nice because it's easy to cover any config file schema or format. E.g. I would appreciate a Helix config at some point, but that uses toml (easy to convert from But 🤷, that may be overkill. |
||
"lsp": { | ||
"rust-analyzer": { | ||
"initialization_options": { | ||
"check": { | ||
"invocationLocation": "root", | ||
"invocationStrategy": "once", | ||
"overrideCommand": ["python3", "x.py", "check", "--json-output"] | ||
}, | ||
"linkedProjects": [ | ||
"Cargo.toml", | ||
"src/tools/x/Cargo.toml", | ||
"src/bootstrap/Cargo.toml", | ||
"src/tools/rust-analyzer/Cargo.toml", | ||
"compiler/rustc_codegen_cranelift/Cargo.toml", | ||
"compiler/rustc_codegen_gcc/Cargo.toml" | ||
], | ||
"rustfmt": { | ||
"overrideCommand": [ | ||
"${workspaceFolder}/build/host/rustfmt/bin/rustfmt", | ||
"--edition=2021" | ||
] | ||
}, | ||
"procMacro": { | ||
"server": "${workspaceFolder}/build/host/stage0/libexec/rust-analyzer-proc-macro-srv", | ||
"enable": true | ||
}, | ||
"cargo": { | ||
"buildScripts": { | ||
"enable": true, | ||
"invocationLocation": "root", | ||
"invocationStrategy": "once", | ||
"overrideCommand": ["python3", "x.py", "check", "--json-output"] | ||
}, | ||
"sysrootSrc": "./library", | ||
"extraEnv": { | ||
"RUSTC_BOOTSTRAP": "1" | ||
} | ||
}, | ||
"rustc": { | ||
"source": "./Cargo.toml" | ||
} | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: This makes it more readable