Skip to main content

lisette_diagnostics/
attribute.rs

1use crate::LisetteDiagnostic;
2use syntax::ast::Span;
3
4pub fn field_attribute_without_struct_attribute(
5    field_span: &Span,
6    attribute_name: &str,
7) -> LisetteDiagnostic {
8    LisetteDiagnostic::error("Orphan field attribute")
9        .with_attribute_code("orphan_field_attribute")
10        .with_span_label(field_span, "field has attribute but struct does not")
11        .with_help(format!(
12            "Add `#[{}]` atop the struct definition to enable field-level attributes",
13            attribute_name
14        ))
15}
16
17pub fn duplicate_tag_key(span: &Span, key: &str, first_span: &Span) -> LisetteDiagnostic {
18    LisetteDiagnostic::error("Duplicate tag")
19        .with_attribute_code("duplicate_tag")
20        .with_span_label(span, "duplicate")
21        .with_span_label(first_span, "first occurrence")
22        .with_help(format!(
23            "Remove one of the `{}` attributes - each tag key may appear only once per field",
24            key
25        ))
26}
27
28pub fn conflicting_case_transforms(span: &Span) -> LisetteDiagnostic {
29    LisetteDiagnostic::error("Conflicting case transforms")
30        .with_attribute_code("conflicting_case_transforms")
31        .with_span_label(span, "conflicting")
32        .with_help("Choose either `snake_case` or `camel_case`, not both")
33}
34
35pub fn iterate_non_unit_variant(attribute_span: &Span, variant_span: &Span) -> LisetteDiagnostic {
36    LisetteDiagnostic::error("`#[iterate]` on enum with payload variant")
37        .with_attribute_code("iterate_non_unit_variant")
38        .with_span_label(attribute_span, "disallowed if a variant has a payload")
39        .with_span_label(variant_span, "this variant has a payload")
40        .with_help("Remove the payload, or drop `#[iterate]`")
41}
42
43pub fn iterate_generic_enum(attribute_span: &Span) -> LisetteDiagnostic {
44    LisetteDiagnostic::error("`#[iterate]` on generic enum")
45        .with_attribute_code("iterate_generic_enum")
46        .with_span_label(attribute_span, "disallowed if enum has generics")
47        .with_help("Remove the generic type parameters, or drop `#[iterate]`")
48}
49
50pub fn iterate_not_an_enum(attribute_span: &Span) -> LisetteDiagnostic {
51    LisetteDiagnostic::error("`#[iterate]` not on enum")
52        .with_attribute_code("iterate_not_an_enum")
53        .with_span_label(attribute_span, "not on an enum")
54        .with_help("Only an enum can be marked `#[iterate]`")
55}
56
57pub fn iterate_in_typedef(attribute_span: &Span) -> LisetteDiagnostic {
58    LisetteDiagnostic::error("`#[iterate]` in a typedef")
59        .with_attribute_code("iterate_in_typedef")
60        .with_span_label(attribute_span, "disallowed in a `.d.lis` typedef")
61        .with_help("Only enums in `.lis` source can be marked `#[iterate]`")
62}
63
64pub fn display_not_a_struct_or_enum(attribute_span: &Span) -> LisetteDiagnostic {
65    LisetteDiagnostic::error("`#[display]` not on a struct or enum")
66        .with_attribute_code("display_not_a_struct_or_enum")
67        .with_span_label(attribute_span, "not on a struct or enum")
68        .with_help("Only a struct or enum can be marked `#[display]`")
69}
70
71pub fn display_in_typedef(attribute_span: &Span) -> LisetteDiagnostic {
72    LisetteDiagnostic::error("`#[display]` in a typedef")
73        .with_attribute_code("display_in_typedef")
74        .with_span_label(attribute_span, "disallowed in a `.d.lis` typedef")
75        .with_help("Only structs or enums in `.lis` source can be marked `#[display]`")
76}
77
78pub fn display_with_arguments(attribute_span: &Span) -> LisetteDiagnostic {
79    LisetteDiagnostic::error("`#[display]` takes no arguments")
80        .with_attribute_code("display_with_arguments")
81        .with_span_label(attribute_span, "remove the arguments")
82        .with_help("Write `#[display]` with no arguments")
83}
84
85pub fn display_on_pointer_newtype(attribute_span: &Span) -> LisetteDiagnostic {
86    LisetteDiagnostic::error("`#[display]` on a pointer-backed newtype")
87        .with_attribute_code("display_on_pointer_newtype")
88        .with_span_label(attribute_span, "a `Ref` has no display form")
89        .with_help("Give the type named fields, or drop `#[display]`")
90}
91
92pub fn display_specialized_to_string(attribute_span: &Span) -> LisetteDiagnostic {
93    LisetteDiagnostic::error("`#[display]` conflicts with your `to_string`")
94        .with_attribute_code("display_specialized_to_string")
95        .with_span_label(attribute_span, "adds a `to_string` of its own")
96        .with_help(
97            "`#[display]` needs a plain `fn to_string(self) -> string` on the type. Write `to_string` in that form, or remove `#[display]`.",
98        )
99}
100
101pub fn iterate_variants_conflict(
102    attribute_span: &Span,
103    existing_span: Option<&Span>,
104) -> LisetteDiagnostic {
105    let mut diagnostic =
106        LisetteDiagnostic::error("`#[iterate]` conflicts with existing `variants`")
107            .with_attribute_code("iterate_variants_conflict")
108            .with_span_label(attribute_span, "would synthesize `variants`");
109    if let Some(span) = existing_span {
110        diagnostic = diagnostic.with_span_label(span, "`variants` already defined here");
111    }
112    diagnostic.with_help("Rename the existing `variants`, or drop `#[iterate]`")
113}