pub struct Label {
pub span: Span,
pub message: Option<String>,
pub style: LabelStyle,
}Fields§
§span: Span§message: Option<String>§style: LabelStyleImplementations§
Source§impl Label
impl Label
Sourcepub fn primary(span: Span, message: impl Into<Option<String>>) -> Self
pub fn primary(span: Span, message: impl Into<Option<String>>) -> Self
Examples found in repository?
examples/compiler.rs (lines 50-53)
39fn main() {
40 let source = r#"fn main() {
41 let name = "hello
42 let x = 42;
43 println(name);
44}"#;
45
46 let mut engine = DiagnosticEngine::<LangError>::new();
47
48 engine.emit(
49 Diagnostic::new(LangError::UnterminatedString, "unterminated string literal")
50 .with_label(Label::primary(
51 Span::new("main.lang", 2, 16, 6),
52 Some("string starts here but never closes".into()),
53 ))
54 .with_help("close the string with a matching `\"`"),
55 );
56
57 engine.emit(
58 Diagnostic::new(LangError::UnusedVariable, "unused variable `x`")
59 .with_label(Label::primary(
60 Span::new("main.lang", 3, 8, 1),
61 Some("declared here but never used".into()),
62 ))
63 .with_help("prefix with `_` to silence: `_x`"),
64 );
65
66 engine.print_all(source);
67}More examples
examples/api_validator.rs (lines 50-53)
38fn main() {
39 let request_body = r#"{
40 "name": "Alice",
41 "age": -5,
42 "email": "not-an-email",
43 "role": "superadmin"
44}"#;
45
46 let mut engine = DiagnosticEngine::<ApiError>::new();
47
48 engine.emit(
49 Diagnostic::new(ApiError::ValueOutOfRange, "`age` must be a positive integer")
50 .with_label(Label::primary(
51 Span::new("POST /users", 3, 9, 2),
52 Some("negative values not allowed".into()),
53 ))
54 .with_help("age must be between 0 and 150"),
55 );
56
57 engine.emit(
58 Diagnostic::new(ApiError::InvalidFormat, "`email` is not a valid email address")
59 .with_label(Label::primary(
60 Span::new("POST /users", 4, 11, 14),
61 Some("missing @ symbol".into()),
62 ))
63 .with_help("expected format: user@domain.com"),
64 );
65
66 engine.emit(
67 Diagnostic::new(ApiError::DeprecatedEndpoint, "POST /users is deprecated, use POST /v2/users")
68 .with_label(Label::primary(Span::new("request", 1, 0, 1), None))
69 .with_note("this endpoint will be removed in v3"),
70 );
71
72 engine.print_all(request_body);
73}examples/sql_engine.rs (lines 48-51)
37fn main() {
38 let query = r#"SELECT u.name, o.total
39FROM users u
40JOIN orders o ON u.id = o.user_id
41WHERE u.age / 0 > 10
42 AND o.status = active"#;
43
44 let mut engine = DiagnosticEngine::<SqlError>::new();
45
46 engine.emit(
47 Diagnostic::new(SqlError::DivisionByZero, "division by zero in expression")
48 .with_label(Label::primary(
49 Span::new("query.sql", 4, 6, 11),
50 Some("this will always fail at runtime".into()),
51 ))
52 .with_note("division by a literal zero is never valid"),
53 );
54
55 engine.emit(
56 Diagnostic::new(SqlError::UnknownColumn, "unknown column `active`")
57 .with_label(Label::primary(
58 Span::new("query.sql", 5, 18, 6),
59 Some("not a known column".into()),
60 ))
61 .with_help("did you mean the string `'active'`?"),
62 );
63
64 engine.emit(
65 Diagnostic::new(SqlError::FullTableScan, "query requires a full table scan on `users`")
66 .with_label(Label::primary(
67 Span::new("query.sql", 2, 5, 7),
68 Some("no index on `users.age`".into()),
69 ))
70 .with_help("consider adding an index: CREATE INDEX idx_users_age ON users(age)"),
71 );
72
73 engine.print_all(query);
74}examples/config_linter.rs (lines 49-52)
36fn main() {
37 let config = r#"[package]
38name = "my-app"
39version = "1.0"
40edition = "2018"
41authors = ["me"]
42authors = ["you"]
43license = 42"#;
44
45 let mut engine = DiagnosticEngine::<ConfigError>::new();
46
47 engine.emit(
48 Diagnostic::new(ConfigError::DuplicateKey, "duplicate key `authors`")
49 .with_label(Label::primary(
50 Span::new("Cargo.toml", 6, 0, 7),
51 Some("second definition here".into()),
52 ))
53 .with_label(Label::secondary(
54 Span::new("Cargo.toml", 5, 0, 7),
55 Some("first defined here".into()),
56 ))
57 .with_help("remove one of the duplicate entries"),
58 );
59
60 engine.emit(
61 Diagnostic::new(ConfigError::InvalidValue, "expected string for `license`, found integer")
62 .with_label(Label::primary(
63 Span::new("Cargo.toml", 7, 10, 2),
64 Some("expected a string like \"MIT\"".into()),
65 )),
66 );
67
68 engine.emit(
69 Diagnostic::new(ConfigError::DeprecatedField, "`edition = \"2018\"` is outdated").with_label(
70 Label::primary(
71 Span::new("Cargo.toml", 4, 0, 18),
72 Some("consider updating to \"2021\" or \"2024\"".into()),
73 ),
74 ),
75 );
76
77 engine.print_all(config);
78}examples/demo.rs (lines 88-91)
74fn demo_compiler() {
75 println!("[compiler]\n");
76
77 let source = r#"fn main() {
78 let name = "hello
79 let x = 42;
80 let result = a + b * c;
81 println(name);
82}"#;
83
84 let mut engine = DiagnosticEngine::<LangError>::new();
85
86 engine.emit(
87 Diagnostic::new(LangError::UnterminatedString, "unterminated string literal")
88 .with_label(Label::primary(
89 Span::new("main.lang", 2, 16, 6),
90 Some("string starts here but never closes".into()),
91 ))
92 .with_help("close the string with a matching `\"`"),
93 );
94
95 engine.emit(
96 Diagnostic::new(LangError::TypeMismatch, "mismatched types in expression")
97 .with_label(Label::primary(
98 Span::new("main.lang", 4, 17, 1),
99 Some("this is a string".into()),
100 ))
101 .with_label(Label::secondary(
102 Span::new("main.lang", 4, 21, 1),
103 Some("this is an int".into()),
104 ))
105 .with_note("cannot add `String` and `i32`")
106 .with_help("convert one side: `a.parse::<i32>()`"),
107 );
108
109 engine.emit(
110 Diagnostic::new(LangError::UnusedVariable, "unused variable `x`")
111 .with_label(Label::primary(
112 Span::new("main.lang", 3, 8, 1),
113 Some("declared here but never used".into()),
114 ))
115 .with_help("prefix with `_` to silence: `_x`"),
116 );
117
118 engine.print_all(source);
119}
120
121fn demo_sql() {
122 println!("\n[sql engine]\n");
123
124 let query = r#"SELECT u.name, o.total
125FROM users u
126JOIN orders o ON u.id = o.user_id
127WHERE u.age / 0 > 10
128 AND o.status = active"#;
129
130 let mut engine = DiagnosticEngine::<SqlError>::new();
131
132 engine.emit(
133 Diagnostic::new(SqlError::DivisionByZero, "division by zero in expression")
134 .with_label(Label::primary(
135 Span::new("query.sql", 4, 6, 11),
136 Some("this will always fail at runtime".into()),
137 ))
138 .with_note("division by a literal zero is never valid"),
139 );
140
141 engine.emit(
142 Diagnostic::new(SqlError::UnknownColumn, "unknown column `active`")
143 .with_label(Label::primary(
144 Span::new("query.sql", 5, 18, 6),
145 Some("not a known column".into()),
146 ))
147 .with_help("did you mean the string `'active'`?"),
148 );
149
150 engine.emit(
151 Diagnostic::new(SqlError::FullTableScan, "query requires a full table scan on `users`")
152 .with_label(Label::primary(
153 Span::new("query.sql", 2, 5, 7),
154 Some("no index on `users.age`".into()),
155 ))
156 .with_help("consider adding an index: CREATE INDEX idx_users_age ON users(age)"),
157 );
158
159 engine.print_all(query);
160}
161
162fn demo_config() {
163 println!("\n[config linter]\n");
164
165 let config = r#"[package]
166name = "my-app"
167version = "1.0"
168edition = "2018"
169authors = ["me"]
170authors = ["you"]
171license = 42"#;
172
173 let mut engine = DiagnosticEngine::<ConfigError>::new();
174
175 engine.emit(
176 Diagnostic::new(ConfigError::DuplicateKey, "duplicate key `authors`")
177 .with_label(Label::primary(
178 Span::new("Cargo.toml", 6, 0, 7),
179 Some("second definition here".into()),
180 ))
181 .with_label(Label::secondary(
182 Span::new("Cargo.toml", 5, 0, 7),
183 Some("first defined here".into()),
184 ))
185 .with_help("remove one of the duplicate entries"),
186 );
187
188 engine.emit(
189 Diagnostic::new(ConfigError::InvalidValue, "expected string for `license`, found integer")
190 .with_label(Label::primary(
191 Span::new("Cargo.toml", 7, 10, 2),
192 Some("expected a string like \"MIT\"".into()),
193 )),
194 );
195
196 engine.emit(
197 Diagnostic::new(ConfigError::DeprecatedField, "`edition = \"2018\"` is outdated")
198 .with_label(Label::primary(
199 Span::new("Cargo.toml", 4, 0, 18),
200 Some("consider updating to \"2021\" or \"2024\"".into()),
201 )),
202 );
203
204 engine.print_all(config);
205}Sourcepub fn secondary(span: Span, message: impl Into<Option<String>>) -> Self
pub fn secondary(span: Span, message: impl Into<Option<String>>) -> Self
Examples found in repository?
examples/config_linter.rs (lines 53-56)
36fn main() {
37 let config = r#"[package]
38name = "my-app"
39version = "1.0"
40edition = "2018"
41authors = ["me"]
42authors = ["you"]
43license = 42"#;
44
45 let mut engine = DiagnosticEngine::<ConfigError>::new();
46
47 engine.emit(
48 Diagnostic::new(ConfigError::DuplicateKey, "duplicate key `authors`")
49 .with_label(Label::primary(
50 Span::new("Cargo.toml", 6, 0, 7),
51 Some("second definition here".into()),
52 ))
53 .with_label(Label::secondary(
54 Span::new("Cargo.toml", 5, 0, 7),
55 Some("first defined here".into()),
56 ))
57 .with_help("remove one of the duplicate entries"),
58 );
59
60 engine.emit(
61 Diagnostic::new(ConfigError::InvalidValue, "expected string for `license`, found integer")
62 .with_label(Label::primary(
63 Span::new("Cargo.toml", 7, 10, 2),
64 Some("expected a string like \"MIT\"".into()),
65 )),
66 );
67
68 engine.emit(
69 Diagnostic::new(ConfigError::DeprecatedField, "`edition = \"2018\"` is outdated").with_label(
70 Label::primary(
71 Span::new("Cargo.toml", 4, 0, 18),
72 Some("consider updating to \"2021\" or \"2024\"".into()),
73 ),
74 ),
75 );
76
77 engine.print_all(config);
78}More examples
examples/demo.rs (lines 101-104)
74fn demo_compiler() {
75 println!("[compiler]\n");
76
77 let source = r#"fn main() {
78 let name = "hello
79 let x = 42;
80 let result = a + b * c;
81 println(name);
82}"#;
83
84 let mut engine = DiagnosticEngine::<LangError>::new();
85
86 engine.emit(
87 Diagnostic::new(LangError::UnterminatedString, "unterminated string literal")
88 .with_label(Label::primary(
89 Span::new("main.lang", 2, 16, 6),
90 Some("string starts here but never closes".into()),
91 ))
92 .with_help("close the string with a matching `\"`"),
93 );
94
95 engine.emit(
96 Diagnostic::new(LangError::TypeMismatch, "mismatched types in expression")
97 .with_label(Label::primary(
98 Span::new("main.lang", 4, 17, 1),
99 Some("this is a string".into()),
100 ))
101 .with_label(Label::secondary(
102 Span::new("main.lang", 4, 21, 1),
103 Some("this is an int".into()),
104 ))
105 .with_note("cannot add `String` and `i32`")
106 .with_help("convert one side: `a.parse::<i32>()`"),
107 );
108
109 engine.emit(
110 Diagnostic::new(LangError::UnusedVariable, "unused variable `x`")
111 .with_label(Label::primary(
112 Span::new("main.lang", 3, 8, 1),
113 Some("declared here but never used".into()),
114 ))
115 .with_help("prefix with `_` to silence: `_x`"),
116 );
117
118 engine.print_all(source);
119}
120
121fn demo_sql() {
122 println!("\n[sql engine]\n");
123
124 let query = r#"SELECT u.name, o.total
125FROM users u
126JOIN orders o ON u.id = o.user_id
127WHERE u.age / 0 > 10
128 AND o.status = active"#;
129
130 let mut engine = DiagnosticEngine::<SqlError>::new();
131
132 engine.emit(
133 Diagnostic::new(SqlError::DivisionByZero, "division by zero in expression")
134 .with_label(Label::primary(
135 Span::new("query.sql", 4, 6, 11),
136 Some("this will always fail at runtime".into()),
137 ))
138 .with_note("division by a literal zero is never valid"),
139 );
140
141 engine.emit(
142 Diagnostic::new(SqlError::UnknownColumn, "unknown column `active`")
143 .with_label(Label::primary(
144 Span::new("query.sql", 5, 18, 6),
145 Some("not a known column".into()),
146 ))
147 .with_help("did you mean the string `'active'`?"),
148 );
149
150 engine.emit(
151 Diagnostic::new(SqlError::FullTableScan, "query requires a full table scan on `users`")
152 .with_label(Label::primary(
153 Span::new("query.sql", 2, 5, 7),
154 Some("no index on `users.age`".into()),
155 ))
156 .with_help("consider adding an index: CREATE INDEX idx_users_age ON users(age)"),
157 );
158
159 engine.print_all(query);
160}
161
162fn demo_config() {
163 println!("\n[config linter]\n");
164
165 let config = r#"[package]
166name = "my-app"
167version = "1.0"
168edition = "2018"
169authors = ["me"]
170authors = ["you"]
171license = 42"#;
172
173 let mut engine = DiagnosticEngine::<ConfigError>::new();
174
175 engine.emit(
176 Diagnostic::new(ConfigError::DuplicateKey, "duplicate key `authors`")
177 .with_label(Label::primary(
178 Span::new("Cargo.toml", 6, 0, 7),
179 Some("second definition here".into()),
180 ))
181 .with_label(Label::secondary(
182 Span::new("Cargo.toml", 5, 0, 7),
183 Some("first defined here".into()),
184 ))
185 .with_help("remove one of the duplicate entries"),
186 );
187
188 engine.emit(
189 Diagnostic::new(ConfigError::InvalidValue, "expected string for `license`, found integer")
190 .with_label(Label::primary(
191 Span::new("Cargo.toml", 7, 10, 2),
192 Some("expected a string like \"MIT\"".into()),
193 )),
194 );
195
196 engine.emit(
197 Diagnostic::new(ConfigError::DeprecatedField, "`edition = \"2018\"` is outdated")
198 .with_label(Label::primary(
199 Span::new("Cargo.toml", 4, 0, 18),
200 Some("consider updating to \"2021\" or \"2024\"".into()),
201 )),
202 );
203
204 engine.print_all(config);
205}Trait Implementations§
Auto Trait Implementations§
impl Freeze for Label
impl RefUnwindSafe for Label
impl Send for Label
impl Sync for Label
impl Unpin for Label
impl UnsafeUnpin for Label
impl UnwindSafe for Label
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more