perl_lsp_diagnostic_catalog/
lib.rs1#![deny(unsafe_code)]
7#![warn(rust_2018_idioms)]
8#![warn(missing_docs)]
9#![warn(clippy::all)]
10
11use perl_diagnostics_codes::DiagnosticCode;
12use serde_json::{Value, json};
13
14pub struct DiagnosticMeta {
16 pub code: Value,
18 pub desc: Option<Value>,
20}
21
22impl DiagnosticMeta {
23 fn from_code(code: DiagnosticCode) -> Self {
24 Self {
25 code: json!(code.as_str()),
26 desc: code.documentation_url().map(|url| json!({ "href": url })),
27 }
28 }
29}
30
31#[must_use]
33pub fn diagnostic_meta(code: DiagnosticCode) -> DiagnosticMeta {
34 DiagnosticMeta::from_code(code)
35}
36
37#[must_use]
39pub fn parse_error() -> DiagnosticMeta {
40 diagnostic_meta(DiagnosticCode::ParseError)
41}
42
43#[must_use]
45pub fn syntax_error() -> DiagnosticMeta {
46 diagnostic_meta(DiagnosticCode::SyntaxError)
47}
48
49#[must_use]
51pub fn unexpected_eof() -> DiagnosticMeta {
52 diagnostic_meta(DiagnosticCode::UnexpectedEof)
53}
54
55#[must_use]
57pub fn missing_strict() -> DiagnosticMeta {
58 diagnostic_meta(DiagnosticCode::MissingStrict)
59}
60
61#[must_use]
63pub fn missing_warnings() -> DiagnosticMeta {
64 diagnostic_meta(DiagnosticCode::MissingWarnings)
65}
66
67#[must_use]
69pub fn unused_var() -> DiagnosticMeta {
70 diagnostic_meta(DiagnosticCode::UnusedVariable)
71}
72
73#[must_use]
75pub fn undefined_var() -> DiagnosticMeta {
76 diagnostic_meta(DiagnosticCode::UndefinedVariable)
77}
78
79#[must_use]
81pub fn missing_package_declaration() -> DiagnosticMeta {
82 diagnostic_meta(DiagnosticCode::MissingPackageDeclaration)
83}
84
85#[must_use]
87pub fn duplicate_package() -> DiagnosticMeta {
88 diagnostic_meta(DiagnosticCode::DuplicatePackage)
89}
90
91#[must_use]
93pub fn duplicate_sub() -> DiagnosticMeta {
94 diagnostic_meta(DiagnosticCode::DuplicateSubroutine)
95}
96
97#[must_use]
99pub fn missing_return() -> DiagnosticMeta {
100 diagnostic_meta(DiagnosticCode::MissingReturn)
101}
102
103#[must_use]
105pub fn bareword_filehandle() -> DiagnosticMeta {
106 diagnostic_meta(DiagnosticCode::BarewordFilehandle)
107}
108
109#[must_use]
111pub fn two_arg_open() -> DiagnosticMeta {
112 diagnostic_meta(DiagnosticCode::TwoArgOpen)
113}
114
115#[must_use]
117pub fn implicit_return() -> DiagnosticMeta {
118 diagnostic_meta(DiagnosticCode::ImplicitReturn)
119}
120
121#[must_use]
123pub fn critic_severity_5() -> DiagnosticMeta {
124 diagnostic_meta(DiagnosticCode::CriticSeverity5)
125}
126
127#[must_use]
129pub fn critic_severity_4() -> DiagnosticMeta {
130 diagnostic_meta(DiagnosticCode::CriticSeverity4)
131}
132
133#[must_use]
135pub fn critic_severity_3() -> DiagnosticMeta {
136 diagnostic_meta(DiagnosticCode::CriticSeverity3)
137}
138
139#[must_use]
141pub fn critic_severity_2() -> DiagnosticMeta {
142 diagnostic_meta(DiagnosticCode::CriticSeverity2)
143}
144
145#[must_use]
147pub fn critic_severity_1() -> DiagnosticMeta {
148 diagnostic_meta(DiagnosticCode::CriticSeverity1)
149}
150
151#[must_use]
153pub fn from_message(msg: &str) -> Option<DiagnosticMeta> {
154 DiagnosticCode::from_message(msg).map(diagnostic_meta)
155}
156
157#[cfg(test)]
158mod tests {
159 use super::{from_message, parse_error};
160
161 #[test]
162 fn parse_error_includes_stable_code_and_docs_url() {
163 let meta = parse_error();
164 assert_eq!(meta.code, "PL001");
165 assert_eq!(
166 meta.desc,
167 Some(serde_json::json!({ "href": "https://docs.perl-lsp.org/errors/PL001" }))
168 );
169 }
170
171 #[test]
172 fn critic_codes_have_no_docs_url() {
173 let meta = super::critic_severity_1();
174 assert_eq!(meta.code, "PC001");
175 assert!(meta.desc.is_none());
176 }
177
178 #[test]
179 fn message_inference_is_case_insensitive() {
180 let meta = from_message("Missing USE STRICT pragma");
181 assert!(meta.is_some());
182 assert_eq!(meta.as_ref().map(|m| &m.code), Some(&serde_json::json!("PL100")));
183 }
184}