format.rs

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