1use collections::HashMap;
2use schemars::{
3 JsonSchema,
4 r#gen::SchemaSettings,
5 schema::{ObjectValidation, Schema, SchemaObject},
6};
7use serde::Deserialize;
8use serde_json_lenient::Value;
9
10#[derive(Deserialize)]
11pub struct VsSnippetsFile {
12 #[serde(flatten)]
13 pub(crate) snippets: HashMap<String, VsCodeSnippet>,
14}
15
16impl VsSnippetsFile {
17 pub fn generate_json_schema() -> Value {
18 let schema = SchemaSettings::draft07()
19 .with(|settings| settings.option_add_null_type = false)
20 .into_generator()
21 .into_root_schema_for::<Self>();
22
23 serde_json_lenient::to_value(schema).unwrap()
24 }
25}
26
27impl JsonSchema for VsSnippetsFile {
28 fn schema_name() -> String {
29 "VsSnippetsFile".into()
30 }
31
32 fn json_schema(r#gen: &mut schemars::r#gen::SchemaGenerator) -> Schema {
33 SchemaObject {
34 object: Some(Box::new(ObjectValidation {
35 additional_properties: Some(Box::new(r#gen.subschema_for::<VsCodeSnippet>())),
36 ..Default::default()
37 })),
38 ..Default::default()
39 }
40 .into()
41 }
42}
43
44#[derive(Deserialize, JsonSchema)]
45#[serde(untagged)]
46pub(crate) enum ListOrDirect {
47 Single(String),
48 List(Vec<String>),
49}
50
51impl From<ListOrDirect> for Vec<String> {
52 fn from(list: ListOrDirect) -> Self {
53 match list {
54 ListOrDirect::Single(entry) => vec![entry],
55 ListOrDirect::List(entries) => entries,
56 }
57 }
58}
59
60impl std::fmt::Display for ListOrDirect {
61 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
62 write!(
63 f,
64 "{}",
65 match self {
66 Self::Single(v) => v.to_owned(),
67 Self::List(v) => v.join("\n"),
68 }
69 )
70 }
71}
72
73#[derive(Deserialize, JsonSchema)]
74pub(crate) struct VsCodeSnippet {
75 /// The snippet prefix used to decide whether a completion menu should be shown.
76 pub(crate) prefix: Option<ListOrDirect>,
77
78 /// The snippet content. Use `$1` and `${1:defaultText}` to define cursor positions and `$0` for final cursor position.
79 pub(crate) body: ListOrDirect,
80
81 /// The snippet description displayed inside the completion menu.
82 pub(crate) description: Option<ListOrDirect>,
83}