Files
zed/crates/feature_flags/src/settings.rs
T
Mikayla Maki ec9be5c332 Feature flag overrides (#54206)
This PR revamps our feature flag system, to enable richer iteration. 

Feature flags can now:
- Support enum values, for richer configuration
- Be manually set via the settings file
- Be manually set via the settings UI

This PR also adds a feature flag to demonstrate this behavior, a
`agent-thread-worktree-label`, which controls which how the worktree tag
UI displays.

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- N/A
2026-04-18 06:34:19 +00:00

77 lines
2.7 KiB
Rust

use collections::HashMap;
use schemars::{Schema, json_schema};
use serde_json::{Map, Value};
use settings::{RegisterSetting, Settings, SettingsContent};
use crate::FeatureFlagStore;
#[derive(Clone, Debug, Default, RegisterSetting)]
pub struct FeatureFlagsSettings {
pub overrides: HashMap<String, String>,
}
impl Settings for FeatureFlagsSettings {
fn from_settings(content: &SettingsContent) -> Self {
Self {
overrides: content
.feature_flags
.as_ref()
.map(|map| map.0.clone())
.unwrap_or_default(),
}
}
}
/// Produces a JSON schema for the `feature_flags` object that lists each known
/// flag as a property with its variant keys as an `enum`.
///
/// Unknown flags are permitted via `additionalProperties: { "type": "string" }`,
/// so removing a flag from the binary never turns existing entries in
/// `settings.json` into validation errors.
pub fn generate_feature_flags_schema() -> Schema {
let mut properties = Map::new();
for descriptor in FeatureFlagStore::known_flags() {
let variants = (descriptor.variants)();
let enum_values: Vec<Value> = variants
.iter()
.map(|v| Value::String(v.override_key.to_string()))
.collect();
let enum_descriptions: Vec<Value> = variants
.iter()
.map(|v| Value::String(v.label.to_string()))
.collect();
let mut property = Map::new();
property.insert("type".to_string(), Value::String("string".to_string()));
property.insert("enum".to_string(), Value::Array(enum_values));
// VS Code / json-language-server use `enumDescriptions` for hover docs
// on each enum value; schemars passes them through untouched.
property.insert(
"enumDescriptions".to_string(),
Value::Array(enum_descriptions),
);
property.insert(
"description".to_string(),
Value::String(format!(
"Override for the `{}` feature flag. Default: `{}` (the {} variant).",
descriptor.name,
(descriptor.default_variant_key)(),
(descriptor.default_variant_key)(),
)),
);
properties.insert(descriptor.name.to_string(), Value::Object(property));
}
json_schema!({
"type": "object",
"description": "Local overrides for feature flags, keyed by flag name.",
"properties": properties,
"additionalProperties": {
"type": "string",
"description": "Unknown feature flag; retained so removed flags don't trip settings validation."
}
})
}