Skip to content

Commit 17b211f

Browse files
committed
feat(ls): add support for date types in the metadata validator.
Besides the types `string`, `integer`, `float` and `bool`, the metadata validator now accepts a new type `date` which is actually a string that represents a date. The date format can be specified in an additional `format` field (example: `%Y-%m-%d`).
1 parent 2619a6e commit 17b211f

6 files changed

Lines changed: 100 additions & 36 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ls/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ default = ["full-compiler"]
3535

3636
[dependencies]
3737
bitflags = { workspace = true }
38+
chrono = { workspace = true, features = ["serde"] }
3839
dashmap = { version = "6.1.0" }
3940
futures = "0.3.32"
4041
regex = { workspace = true }

ls/editors/code/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,12 @@ the following properties:
8282
* `identifier` (string, required): The name of the metadata field to validate (e.g., `author`, `version`).
8383
* `required` (boolean, optional): If `true`, the metadata field must be present in the rule. Defaults to `false`.
8484
* `type` (string, optional): Specifies the expected type of the metadata value. Valid values are
85-
`"string"`, `"integer"`, `"float"`, and `"bool"`. If the value does not match the specified type, a warning will
86-
be generated.
85+
`"string"`, `"integer"`, `"float"`, `"bool"`, and `"date"`. If the value does not match the specified type, a
86+
warning will be generated.
87+
* `format` (string, optional): When `type` is `"date"`, this property specifies the expected format of the
88+
date string. The format string supports specifiers like `%Y` (year), `%m` (month), `%d` (day), `%H` (hour),
89+
`%M` (minute), and `%S` (second). For example, for a date like `"2024-01-25"`, the format should be `"%Y-%m-%d"`.
90+
For more information see: https://docs.rs/chrono/latest/chrono/format/strftime/index.html
8791

8892
For accessing these settings go to the Settings
8993

ls/editors/code/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,12 @@
9494
},
9595
"type": {
9696
"type": "string",
97-
"enum": ["string", "integer", "float", "bool"],
97+
"enum": ["string", "integer", "float", "bool", "date"],
9898
"description": "The expected type of the metadata value."
99+
},
100+
"format": {
101+
"type": "string",
102+
"description": "The expected format of the date string (e.g., `%Y-%m-%d`)."
99103
}
100104
}
101105
}

ls/src/configuration.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,6 @@ pub struct MetadataValidationRule {
5151
/// Type of the metadata entry.
5252
#[serde(rename = "type")]
5353
pub ty: Option<String>,
54+
/// Format of the metadata entry, if type is "date".
55+
pub format: Option<String>,
5456
}

ls/src/features/diagnostics.rs

Lines changed: 84 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use dashmap::mapref::one::Ref;
1010
use serde::{Deserialize, Serialize};
1111

1212
use crate::configuration::MetadataValidationRule;
13+
use chrono::NaiveDate;
1314

1415
#[cfg(feature = "full-compiler")]
1516
use crate::documents::document::Document;
@@ -88,44 +89,94 @@ pub fn compiler_diagnostics(
8889
}
8990

9091
for validation_rule in metadata_validation {
91-
let mut linter = linters::metadata(&validation_rule.identifier)
92+
let linter = linters::metadata(&validation_rule.identifier)
9293
.required(validation_rule.required);
9394

9495
if let Some(ty) = &validation_rule.ty {
95-
let predicate = match ty.as_str() {
96-
"string" => |meta: &yara_x_parser::ast::Meta| {
97-
matches!(
98-
meta.value,
99-
yara_x_parser::ast::MetaValue::String(_)
100-
)
101-
},
102-
"integer" => |meta: &yara_x_parser::ast::Meta| {
103-
matches!(
104-
meta.value,
105-
yara_x_parser::ast::MetaValue::Integer(_)
106-
)
107-
},
108-
"float" => |meta: &yara_x_parser::ast::Meta| {
109-
matches!(
110-
meta.value,
111-
yara_x_parser::ast::MetaValue::Float(_)
112-
)
113-
},
114-
"bool" => |meta: &yara_x_parser::ast::Meta| {
115-
matches!(
116-
meta.value,
117-
yara_x_parser::ast::MetaValue::Bool(_)
118-
)
119-
},
120-
_ => continue,
96+
match ty.as_str() {
97+
"string" => {
98+
compiler.add_linter(linter.validator(
99+
|meta| {
100+
matches!(
101+
meta.value,
102+
yara_x_parser::ast::MetaValue::String(_)
103+
)
104+
},
105+
format!(
106+
"`{}` must be a `string`",
107+
validation_rule.identifier
108+
),
109+
));
110+
}
111+
"integer" => {
112+
compiler.add_linter(linter.validator(
113+
|meta| {
114+
matches!(
115+
meta.value,
116+
yara_x_parser::ast::MetaValue::Integer(_)
117+
)
118+
},
119+
format!(
120+
"`{}` must be a `integer`",
121+
validation_rule.identifier
122+
),
123+
));
124+
}
125+
"float" => {
126+
compiler.add_linter(linter.validator(
127+
|meta| {
128+
matches!(
129+
meta.value,
130+
yara_x_parser::ast::MetaValue::Float(_)
131+
)
132+
},
133+
format!(
134+
"`{}` must be a `float`",
135+
validation_rule.identifier
136+
),
137+
));
138+
}
139+
"bool" => {
140+
compiler.add_linter(linter.validator(
141+
|meta| {
142+
matches!(
143+
meta.value,
144+
yara_x_parser::ast::MetaValue::Float(_)
145+
)
146+
},
147+
format!(
148+
"`{}` must be a `bool`",
149+
validation_rule.identifier
150+
),
151+
));
152+
}
153+
"date" => {
154+
let format = validation_rule
155+
.format
156+
.as_deref()
157+
.unwrap_or("%Y-%m-%d");
158+
159+
compiler.add_linter(linter.validator(
160+
|meta| {
161+
if let yara_x_parser::ast::MetaValue::String(
162+
value,
163+
) = &meta.value
164+
{
165+
NaiveDate::parse_from_str(value.0, format)
166+
.is_ok()
167+
} else {
168+
false
169+
}
170+
},
171+
format!(
172+
"`{}` must be a `date` with format `{}`",
173+
validation_rule.identifier, format
174+
),
175+
));
176+
}
177+
_ => {}
121178
};
122-
linter = linter.validator(
123-
predicate,
124-
format!("`{}` must be a `{}`", validation_rule.identifier, ty),
125-
);
126179
}
127-
128-
compiler.add_linter(linter);
129180
}
130181

131182
// VSCode don't handle well error messages with too many columns.

0 commit comments

Comments
 (0)