Add binary for exporting JSON schemas for validating extensions (#7639)

Release Notes:

- N/A

Co-authored-by: Marshall <marshall@zed.dev>
This commit is contained in:
Max Brunsfeld 2024-02-09 15:50:41 -08:00 committed by GitHub
parent 3635d2dced
commit 36b89571e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 60 additions and 15 deletions

1
Cargo.lock generated
View file

@ -2681,6 +2681,7 @@ dependencies = [
"gpui", "gpui",
"language", "language",
"parking_lot 0.11.2", "parking_lot 0.11.2",
"schemars",
"serde", "serde",
"serde_json", "serde_json",
"theme", "theme",

View file

@ -8,6 +8,10 @@ license = "GPL-3.0-or-later"
[lib] [lib]
path = "src/extension_store.rs" path = "src/extension_store.rs"
[[bin]]
name = "extension_json_schemas"
path = "src/extension_json_schemas.rs"
[dependencies] [dependencies]
anyhow.workspace = true anyhow.workspace = true
collections.workspace = true collections.workspace = true
@ -16,6 +20,7 @@ futures.workspace = true
gpui.workspace = true gpui.workspace = true
language.workspace = true language.workspace = true
parking_lot.workspace = true parking_lot.workspace = true
schemars.workspace = true
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
theme.workspace = true theme.workspace = true

View file

@ -0,0 +1,17 @@
use language::LanguageConfig;
use schemars::schema_for;
use theme::ThemeFamilyContent;
fn main() {
let theme_family_schema = schema_for!(ThemeFamilyContent);
let language_config_schema = schema_for!(LanguageConfig);
println!(
"{}",
serde_json::to_string_pretty(&theme_family_schema).unwrap()
);
println!(
"{}",
serde_json::to_string_pretty(&language_config_schema).unwrap()
);
}

View file

@ -28,6 +28,11 @@ use lazy_static::lazy_static;
use lsp::{CodeActionKind, LanguageServerBinary}; use lsp::{CodeActionKind, LanguageServerBinary};
use parking_lot::Mutex; use parking_lot::Mutex;
use regex::Regex; use regex::Regex;
use schemars::{
gen::SchemaGenerator,
schema::{InstanceType, Schema, SchemaObject},
JsonSchema,
};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use serde_json::Value; use serde_json::Value;
use std::{ use std::{
@ -363,7 +368,7 @@ pub struct CodeLabel {
pub filter_range: Range<usize>, pub filter_range: Range<usize>,
} }
#[derive(Clone, Deserialize)] #[derive(Clone, Deserialize, JsonSchema)]
pub struct LanguageConfig { pub struct LanguageConfig {
/// Human-readable name of the language. /// Human-readable name of the language.
pub name: Arc<str>, pub name: Arc<str>,
@ -374,6 +379,7 @@ pub struct LanguageConfig {
pub matcher: LanguageMatcher, pub matcher: LanguageMatcher,
/// List of bracket types in a language. /// List of bracket types in a language.
#[serde(default)] #[serde(default)]
#[schemars(schema_with = "bracket_pair_config_json_schema")]
pub brackets: BracketPairConfig, pub brackets: BracketPairConfig,
/// If set to true, auto indentation uses last non empty line to determine /// If set to true, auto indentation uses last non empty line to determine
/// the indentation level for a new line. /// the indentation level for a new line.
@ -382,10 +388,12 @@ pub struct LanguageConfig {
/// A regex that is used to determine whether the indentation level should be /// A regex that is used to determine whether the indentation level should be
/// increased in the following line. /// increased in the following line.
#[serde(default, deserialize_with = "deserialize_regex")] #[serde(default, deserialize_with = "deserialize_regex")]
#[schemars(schema_with = "regex_json_schema")]
pub increase_indent_pattern: Option<Regex>, pub increase_indent_pattern: Option<Regex>,
/// A regex that is used to determine whether the indentation level should be /// A regex that is used to determine whether the indentation level should be
/// decreased in the following line. /// decreased in the following line.
#[serde(default, deserialize_with = "deserialize_regex")] #[serde(default, deserialize_with = "deserialize_regex")]
#[schemars(schema_with = "regex_json_schema")]
pub decrease_indent_pattern: Option<Regex>, pub decrease_indent_pattern: Option<Regex>,
/// A list of characters that trigger the automatic insertion of a closing /// A list of characters that trigger the automatic insertion of a closing
/// bracket when they immediately precede the point where an opening /// bracket when they immediately precede the point where an opening
@ -418,7 +426,7 @@ pub struct LanguageConfig {
pub prettier_parser_name: Option<String>, pub prettier_parser_name: Option<String>,
} }
#[derive(Clone, Debug, Serialize, Deserialize, Default)] #[derive(Clone, Debug, Serialize, Deserialize, Default, JsonSchema)]
pub struct LanguageMatcher { pub struct LanguageMatcher {
/// Given a list of `LanguageConfig`'s, the language of a file can be determined based on the path extension matching any of the `path_suffixes`. /// Given a list of `LanguageConfig`'s, the language of a file can be determined based on the path extension matching any of the `path_suffixes`.
#[serde(default)] #[serde(default)]
@ -429,6 +437,7 @@ pub struct LanguageMatcher {
serialize_with = "serialize_regex", serialize_with = "serialize_regex",
deserialize_with = "deserialize_regex" deserialize_with = "deserialize_regex"
)] )]
#[schemars(schema_with = "regex_json_schema")]
pub first_line_pattern: Option<Regex>, pub first_line_pattern: Option<Regex>,
} }
@ -441,13 +450,14 @@ pub struct LanguageScope {
override_id: Option<u32>, override_id: Option<u32>,
} }
#[derive(Clone, Deserialize, Default, Debug)] #[derive(Clone, Deserialize, Default, Debug, JsonSchema)]
pub struct LanguageConfigOverride { pub struct LanguageConfigOverride {
#[serde(default)] #[serde(default)]
pub line_comments: Override<Vec<Arc<str>>>, pub line_comments: Override<Vec<Arc<str>>>,
#[serde(default)] #[serde(default)]
pub block_comment: Override<(Arc<str>, Arc<str>)>, pub block_comment: Override<(Arc<str>, Arc<str>)>,
#[serde(skip_deserializing)] #[serde(skip_deserializing)]
#[schemars(skip)]
pub disabled_bracket_ixs: Vec<u16>, pub disabled_bracket_ixs: Vec<u16>,
#[serde(default)] #[serde(default)]
pub word_characters: Override<HashSet<char>>, pub word_characters: Override<HashSet<char>>,
@ -455,7 +465,7 @@ pub struct LanguageConfigOverride {
pub opt_into_language_servers: Vec<String>, pub opt_into_language_servers: Vec<String>,
} }
#[derive(Clone, Deserialize, Debug)] #[derive(Clone, Deserialize, Debug, Serialize, JsonSchema)]
#[serde(untagged)] #[serde(untagged)]
pub enum Override<T> { pub enum Override<T> {
Remove { remove: bool }, Remove { remove: bool },
@ -513,6 +523,13 @@ fn deserialize_regex<'de, D: Deserializer<'de>>(d: D) -> Result<Option<Regex>, D
} }
} }
fn regex_json_schema(_: &mut SchemaGenerator) -> Schema {
Schema::Object(SchemaObject {
instance_type: Some(InstanceType::String.into()),
..Default::default()
})
}
fn serialize_regex<S>(regex: &Option<Regex>, serializer: S) -> Result<S::Ok, S::Error> fn serialize_regex<S>(regex: &Option<Regex>, serializer: S) -> Result<S::Ok, S::Error>
where where
S: Serializer, S: Serializer,
@ -539,29 +556,34 @@ pub struct FakeLspAdapter {
/// ///
/// This struct includes settings for defining which pairs of characters are considered brackets and /// This struct includes settings for defining which pairs of characters are considered brackets and
/// also specifies any language-specific scopes where these pairs should be ignored for bracket matching purposes. /// also specifies any language-specific scopes where these pairs should be ignored for bracket matching purposes.
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default, JsonSchema)]
pub struct BracketPairConfig { pub struct BracketPairConfig {
/// A list of character pairs that should be treated as brackets in the context of a given language. /// A list of character pairs that should be treated as brackets in the context of a given language.
pub pairs: Vec<BracketPair>, pub pairs: Vec<BracketPair>,
/// A list of tree-sitter scopes for which a given bracket should not be active. /// A list of tree-sitter scopes for which a given bracket should not be active.
/// N-th entry in `[Self::disabled_scopes_by_bracket_ix]` contains a list of disabled scopes for an n-th entry in `[Self::pairs]` /// N-th entry in `[Self::disabled_scopes_by_bracket_ix]` contains a list of disabled scopes for an n-th entry in `[Self::pairs]`
#[schemars(skip)]
pub disabled_scopes_by_bracket_ix: Vec<Vec<String>>, pub disabled_scopes_by_bracket_ix: Vec<Vec<String>>,
} }
fn bracket_pair_config_json_schema(gen: &mut SchemaGenerator) -> Schema {
Option::<Vec<BracketPairContent>>::json_schema(gen)
}
#[derive(Deserialize, JsonSchema)]
pub struct BracketPairContent {
#[serde(flatten)]
pub bracket_pair: BracketPair,
#[serde(default)]
pub not_in: Vec<String>,
}
impl<'de> Deserialize<'de> for BracketPairConfig { impl<'de> Deserialize<'de> for BracketPairConfig {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
#[derive(Deserialize)] let result = Vec::<BracketPairContent>::deserialize(deserializer)?;
pub struct Entry {
#[serde(flatten)]
pub bracket_pair: BracketPair,
#[serde(default)]
pub not_in: Vec<String>,
}
let result = Vec::<Entry>::deserialize(deserializer)?;
let mut brackets = Vec::with_capacity(result.len()); let mut brackets = Vec::with_capacity(result.len());
let mut disabled_scopes_by_bracket_ix = Vec::with_capacity(result.len()); let mut disabled_scopes_by_bracket_ix = Vec::with_capacity(result.len());
for entry in result { for entry in result {
@ -578,7 +600,7 @@ impl<'de> Deserialize<'de> for BracketPairConfig {
/// Describes a single bracket pair and how an editor should react to e.g. inserting /// Describes a single bracket pair and how an editor should react to e.g. inserting
/// an opening bracket or to a newline character insertion in between `start` and `end` characters. /// an opening bracket or to a newline character insertion in between `start` and `end` characters.
#[derive(Clone, Debug, Default, Deserialize, PartialEq)] #[derive(Clone, Debug, Default, Deserialize, PartialEq, JsonSchema)]
pub struct BracketPair { pub struct BracketPair {
/// Starting substring for a bracket. /// Starting substring for a bracket.
pub start: String, pub start: String,