Skip to content

Commit d5b1102

Browse files
authored
feat: Restrict defs (#138)
1 parent b6305c0 commit d5b1102

22 files changed

Lines changed: 557 additions & 345 deletions

crates/plotnik-lib/src/diagnostics/message.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ pub enum DiagnosticKind {
7474
InvalidChildType,
7575

7676
// Often consequences of earlier errors
77-
UnnamedDefNotLast,
77+
UnnamedDef,
7878
}
7979

8080
impl DiagnosticKind {
@@ -119,7 +119,7 @@ impl DiagnosticKind {
119119
/// Consequence errors - often caused by earlier parse errors.
120120
/// These get suppressed when any root-cause or structural error exists.
121121
pub fn is_consequence_error(&self) -> bool {
122-
matches!(self, Self::UnnamedDefNotLast)
122+
matches!(self, Self::UnnamedDef)
123123
}
124124

125125
/// Base message for this diagnostic kind, used when no custom message is provided.
@@ -189,7 +189,7 @@ impl DiagnosticKind {
189189
Self::InvalidChildType => "node type not valid as child",
190190

191191
// Structural
192-
Self::UnnamedDefNotLast => "only the last definition can be unnamed",
192+
Self::UnnamedDef => "definitions must be named",
193193
}
194194
}
195195

@@ -229,8 +229,8 @@ impl DiagnosticKind {
229229
"type annotations use `::`, not `:` — {}".to_string()
230230
}
231231

232-
// Named def ordering
233-
Self::UnnamedDefNotLast => "only the last definition can be unnamed — {}".to_string(),
232+
// Named def
233+
Self::UnnamedDef => "definitions must be named — {}".to_string(),
234234

235235
// Standard pattern: fallback + context
236236
_ => format!("{}; {{}}", self.fallback_message()),

crates/plotnik-lib/src/diagnostics/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ impl Diagnostics {
8585
/// 1. Containment: when error A's suppression_range contains error B's display range,
8686
/// and A has higher priority, suppress B (only for structural errors)
8787
/// 2. Same position: when spans start at the same position, root-cause errors suppress structural ones
88-
/// 3. Consequence errors (UnnamedDefNotLast) suppressed when any other error exists
88+
/// 3. Consequence errors (UnnamedDef) suppressed when any other error exists
8989
/// 4. Adjacent: when error A ends exactly where error B starts, A suppresses B
9090
pub(crate) fn filtered(&self) -> Vec<DiagnosticMessage> {
9191
if self.messages.is_empty() {

crates/plotnik-lib/src/diagnostics/tests.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -271,23 +271,23 @@ fn diagnostic_kind_default_severity() {
271271
Severity::Error
272272
);
273273
assert_eq!(
274-
DiagnosticKind::UnnamedDefNotLast.default_severity(),
274+
DiagnosticKind::UnnamedDef.default_severity(),
275275
Severity::Error
276276
);
277277
}
278278

279279
#[test]
280280
fn diagnostic_kind_suppression_order() {
281281
// Higher priority (earlier in enum) suppresses lower priority (later in enum)
282-
assert!(DiagnosticKind::UnclosedTree.suppresses(&DiagnosticKind::UnnamedDefNotLast));
282+
assert!(DiagnosticKind::UnclosedTree.suppresses(&DiagnosticKind::UnnamedDef));
283283
assert!(DiagnosticKind::UnclosedTree.suppresses(&DiagnosticKind::UndefinedReference));
284-
assert!(DiagnosticKind::ExpectedExpression.suppresses(&DiagnosticKind::UnnamedDefNotLast));
284+
assert!(DiagnosticKind::ExpectedExpression.suppresses(&DiagnosticKind::UnnamedDef));
285285

286286
// Same kind doesn't suppress itself
287287
assert!(!DiagnosticKind::UnclosedTree.suppresses(&DiagnosticKind::UnclosedTree));
288288

289289
// Lower priority doesn't suppress higher priority
290-
assert!(!DiagnosticKind::UnnamedDefNotLast.suppresses(&DiagnosticKind::UnclosedTree));
290+
assert!(!DiagnosticKind::UnnamedDef.suppresses(&DiagnosticKind::UnclosedTree));
291291
}
292292

293293
#[test]
@@ -364,7 +364,7 @@ fn filtered_no_suppression_disjoint_spans() {
364364
#[test]
365365
fn filtered_suppresses_lower_priority_contained() {
366366
let mut diagnostics = Diagnostics::new();
367-
// Higher priority error (UnclosedTree) contains lower priority (UnnamedDefNotLast)
367+
// Higher priority error (UnclosedTree) contains lower priority (UnnamedDef)
368368
diagnostics
369369
.report(
370370
DiagnosticKind::UnclosedTree,
@@ -373,7 +373,7 @@ fn filtered_suppresses_lower_priority_contained() {
373373
.emit();
374374
diagnostics
375375
.report(
376-
DiagnosticKind::UnnamedDefNotLast,
376+
DiagnosticKind::UnnamedDef,
377377
TextRange::new(5.into(), 15.into()),
378378
)
379379
.emit();
@@ -386,10 +386,10 @@ fn filtered_suppresses_lower_priority_contained() {
386386
#[test]
387387
fn filtered_consequence_suppressed_by_structural() {
388388
let mut diagnostics = Diagnostics::new();
389-
// Consequence error (UnnamedDefNotLast) suppressed when structural error (UnclosedTree) exists
389+
// Consequence error (UnnamedDef) suppressed when structural error (UnclosedTree) exists
390390
diagnostics
391391
.report(
392-
DiagnosticKind::UnnamedDefNotLast,
392+
DiagnosticKind::UnnamedDef,
393393
TextRange::new(0.into(), 20.into()),
394394
)
395395
.emit();
@@ -418,7 +418,7 @@ fn filtered_same_span_higher_priority_wins() {
418418
.emit();
419419
diagnostics
420420
.report(
421-
DiagnosticKind::UnnamedDefNotLast,
421+
DiagnosticKind::UnnamedDef,
422422
TextRange::new(0.into(), 10.into()),
423423
)
424424
.emit();
@@ -448,7 +448,7 @@ fn render_filtered() {
448448
.emit();
449449
diagnostics
450450
.report(
451-
DiagnosticKind::UnnamedDefNotLast,
451+
DiagnosticKind::UnnamedDef,
452452
TextRange::new(5.into(), 15.into()),
453453
)
454454
.message("unnamed def")

0 commit comments

Comments
 (0)