php_parser_rs/parser/
error.rs

1use std::fmt::{Display, Formatter};
2
3use ariadne::{CharSet, Color, Config, Label, Report, ReportKind, Source};
4use schemars::JsonSchema;
5use serde::Deserialize;
6use serde::Serialize;
7
8use crate::lexer::error::SyntaxError;
9use crate::lexer::token::{Span, Token, TokenKind};
10use crate::parser::ast::attributes::AttributeGroup;
11use crate::parser::ast::data_type::Type;
12use crate::parser::ast::modifiers::PromotedPropertyModifier;
13use crate::parser::ast::Program;
14
15use super::ast::identifiers::SimpleIdentifier;
16use super::ast::variables::SimpleVariable;
17use super::state::State;
18
19pub type ParseResult<T> = Result<T, ParseError>;
20
21#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, JsonSchema)]
22#[serde(tag = "type")]
23pub enum ParseErrorAnnotationType {
24    Hint,
25    Error,
26}
27
28#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, JsonSchema)]
29pub struct ParseErrorAnnotation {
30    pub r#type: ParseErrorAnnotationType,
31    pub message: String,
32    pub position: usize,
33    pub length: usize,
34}
35
36#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, JsonSchema)]
37pub struct ParseError {
38    pub id: String,
39    pub message: String,
40    pub span: Span,
41    pub annotations: Vec<ParseErrorAnnotation>,
42    pub note: Option<String>,
43}
44
45#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, JsonSchema)]
46pub struct ParseErrorStack {
47    pub partial: Program,
48    pub errors: Vec<ParseError>,
49}
50
51impl ParseErrorStack {
52    pub fn report<'a>(
53        &self,
54        source: &'a str,
55        origin: Option<&'a str>,
56        colored: bool,
57        ascii: bool,
58    ) -> std::io::Result<String> {
59        let mut reports = Vec::new();
60
61        for error in &self.errors {
62            reports.push(error.report(source, origin, colored, ascii)?);
63        }
64
65        Ok(reports.join("\n"))
66    }
67}
68
69impl ParseError {
70    pub fn new<TId: ToString, TMessage: ToString>(id: TId, message: TMessage, span: Span) -> Self {
71        Self {
72            id: id.to_string(),
73            message: message.to_string(),
74            span,
75            annotations: Vec::new(),
76            note: None,
77        }
78    }
79
80    pub fn highlight(mut self, position: usize, length: usize) -> Self {
81        self.annotations.push(ParseErrorAnnotation {
82            r#type: ParseErrorAnnotationType::Hint,
83            message: "".to_owned(),
84            position,
85            length,
86        });
87
88        self
89    }
90
91    pub fn error<T: ToString>(mut self, message: T, position: usize, length: usize) -> Self {
92        self.annotations.push(ParseErrorAnnotation {
93            r#type: ParseErrorAnnotationType::Error,
94            message: message.to_string(),
95            position,
96            length,
97        });
98
99        self
100    }
101
102    pub fn note<T: ToString>(mut self, note: T) -> Self {
103        self.note = Some(note.to_string());
104
105        self
106    }
107
108    pub fn report<'a>(
109        &self,
110        source: &'a str,
111        origin: Option<&'a str>,
112        colored: bool,
113        ascii: bool,
114    ) -> std::io::Result<String> {
115        let origin = origin.unwrap_or("input");
116
117        let mut report = Report::build(ReportKind::Error, origin, self.span.position)
118            .with_code(&self.id)
119            .with_message(&self.message)
120            .with_config(
121                Config::default()
122                    .with_color(colored)
123                    .with_char_set(if ascii {
124                        CharSet::Ascii
125                    } else {
126                        CharSet::Unicode
127                    }),
128            );
129
130        for (order, annotation) in self.annotations.iter().enumerate() {
131            let mut label = Label::new((
132                origin,
133                annotation.position..annotation.position + annotation.length,
134            ))
135            .with_order(order.try_into().unwrap());
136
137            if !annotation.message.is_empty() {
138                label = label.with_message(&annotation.message);
139            }
140
141            if colored {
142                label = match annotation.r#type {
143                    ParseErrorAnnotationType::Hint => label.with_color(Color::Cyan),
144                    ParseErrorAnnotationType::Error => label.with_color(Color::Red),
145                };
146            }
147
148            report = report.with_label(label);
149        }
150
151        if let Some(note) = &self.note {
152            report = report.with_note(note);
153        }
154
155        let code = (origin, Source::from(source));
156
157        let mut bytes = Vec::new();
158
159        report.finish().write(code, &mut bytes)?;
160
161        let string = unsafe {
162            // SAFETY: We know that the bytes are valid UTF-8
163            String::from_utf8_unchecked(bytes)
164        };
165
166        Ok(string)
167    }
168}
169
170pub fn unexpected_token(expected: Vec<String>, found: &Token) -> ParseError {
171    let (found_name, eof) = match &found.kind {
172        TokenKind::Eof => ("end of file".to_string(), true),
173        kind => match kind {
174            TokenKind::Identifier
175            | TokenKind::QualifiedIdentifier
176            | TokenKind::FullyQualifiedIdentifier => ("identifier".to_string(), false),
177            TokenKind::Variable => ("variable".to_string(), false),
178            TokenKind::LiteralInteger
179            | TokenKind::LiteralFloat
180            | TokenKind::LiteralSingleQuotedString
181            | TokenKind::LiteralDoubleQuotedString => ("literal".to_string(), false),
182            _ => (format!("token `{}`", found.value), false),
183        },
184    };
185
186    if expected.is_empty() {
187        return if eof {
188            ParseError::new("E002", format!("unexpected {}", found_name), found.span)
189        } else {
190            ParseError::new("E003", format!("unexpected {}", found_name), found.span).error(
191                "try removing this".to_string(),
192                found.span.position,
193                found.value.len(),
194            )
195        };
196    }
197
198    let expected: Vec<String> = expected
199        .iter()
200        .map(|s| {
201            if s.starts_with("a ") || s.starts_with("an ") {
202                s.to_string()
203            } else {
204                format!("`{}`", s)
205            }
206        })
207        .collect();
208
209    let length = expected.len();
210    let expected = if length > 2 {
211        let (left, right) = expected.split_at(length - 1);
212
213        format!("{}, or {}", left.join(", "), right[0])
214    } else {
215        expected.join(", or ")
216    };
217
218    ParseError::new(
219        "E005",
220        format!("unexpected {}, expecting {}", found_name, expected),
221        found.span,
222    )
223    .error(
224        format!("expected {}", expected),
225        found.span.position,
226        found.value.len(),
227    )
228}
229
230pub fn unexpected_identifier(expected: Vec<String>, found: String, span: Span) -> ParseError {
231    let length = expected.len();
232    let expected = if length >= 2 {
233        let (left, right) = expected.split_at(length - 1);
234
235        format!("{}`, or `{}", left.join("`, `"), right[0])
236    } else {
237        expected.join("")
238    };
239
240    ParseError::new(
241        "E006",
242        format!(
243            "unexpected identifier `{}`, expecting `{}`",
244            found, expected
245        ),
246        span,
247    )
248    .error(
249        format!("try replacing this with `{}`", expected),
250        span.position,
251        found.len(),
252    )
253}
254
255pub fn multiple_modifiers(modifier: String, first: Span, second: Span) -> ParseError {
256    ParseError::new(
257        "E007",
258        format!("multiple `{}` modifiers are not allowed", modifier),
259        second,
260    )
261    .highlight(first.position, modifier.len())
262    .error("try removing this", second.position, modifier.len())
263}
264
265pub fn multiple_visibility_modifiers(first: (String, Span), second: (String, Span)) -> ParseError {
266    ParseError::new(
267        "E008",
268        "multiple visibility modifiers are not allowed",
269        second.1,
270    )
271    .highlight(first.1.position, first.0.len())
272    .error("try removing this", second.1.position, second.0.len())
273}
274
275pub fn standalone_type_used_as_nullable(ty: &Type, span: Span) -> ParseError {
276    let type_span = ty.first_span();
277    let type_string = ty.to_string();
278
279    ParseError::new(
280        "E009",
281        format!("standalone type `{}` cannot be nullable", type_string),
282        type_span,
283    )
284    .error("try removing this", span.position, 1)
285    .highlight(type_span.position, type_string.len())
286    .note("`never`, `void`, and `mixed` cannot be nullable")
287}
288
289pub fn standalone_type_used_in_union(ty: &Type, span: Span) -> ParseError {
290    let type_span = ty.first_span();
291    let type_string = ty.to_string();
292
293    ParseError::new(
294        "E010",
295        format!(
296            "standalone type `{}` cannot be used in a union",
297            type_string
298        ),
299        type_span,
300    )
301    .error(
302        format!("try using a type other than `{}`", type_string),
303        type_span.position,
304        type_string.len(),
305    )
306    .highlight(span.position, 1)
307    .note("`never`, `void`, `mixed`, and nullable types cannot be used in a union")
308}
309
310pub fn standalone_type_used_in_intersection(ty: &Type, span: Span) -> ParseError {
311    let type_span = ty.first_span();
312    let type_string = ty.to_string();
313
314    ParseError::new(
315        "E011",
316        format!(
317            "standalone type `{}` cannot be used in an intersection",
318            type_string
319        ),
320        type_span,
321    )
322    .error(
323        format!("try using a type other than `{}`", type_string),
324        type_span.position,
325        type_string.len(),
326    )
327    .highlight(span.position, 1)
328    .note("`never`, `void`, `mixed`, and nullable types cannot be used in an intersection")
329}
330
331pub fn try_without_catch_or_finally(try_span: Span, last_right_brace: Span) -> ParseError {
332    ParseError::new(
333        "E012",
334        "cannot use `try` without `catch` or `finally`",
335        try_span,
336    )
337    .highlight(
338        try_span.position,
339        last_right_brace.position - try_span.position + 1,
340    )
341}
342
343pub fn variadic_promoted_property(
344    state: &mut State,
345    class: Option<&SimpleIdentifier>,
346    property: &SimpleVariable,
347    span: Span,
348    modifier: &PromotedPropertyModifier,
349) -> ParseError {
350    let error = ParseError::new(
351        "E013",
352        format!(
353            "promoted property `{}::{}` cannot declare variadic",
354            class
355                .map(|c| state.named(c))
356                .unwrap_or_else(|| "anonymous@class".to_string()),
357            property.name
358        ),
359        span,
360    )
361    .highlight(modifier.span().position, modifier.to_string().len())
362    .highlight(property.span.position, property.name.len())
363    .error("try removing this variadic declaration", span.position, 3);
364
365    if let Some(class) = class {
366        error.highlight(class.span.position, class.value.len())
367    } else {
368        error
369    }
370}
371
372pub fn missing_type_for_readonly_property(
373    state: &mut State,
374    class: Option<&SimpleIdentifier>,
375    property: &SimpleVariable,
376    readonly_span: Span,
377) -> ParseError {
378    let error = ParseError::new(
379        "E014",
380        format!(
381            "missing type for readonly property `{}::{}`",
382            class
383                .map(|c| state.named(c))
384                .unwrap_or_else(|| "anonymous@class".to_string()),
385            property.name
386        ),
387        property.span,
388    )
389    .error(
390        format!("try adding a type before `{}`", property.name),
391        property.span.position,
392        property.name.len(),
393    )
394    .highlight(readonly_span.position, 8);
395
396    if let Some(class) = class {
397        error.highlight(class.span.position, class.value.len())
398    } else {
399        error
400    }
401}
402
403pub fn abstract_method_on_a_non_abstract_class(
404    state: &mut State,
405    class: &SimpleIdentifier,
406    method: &SimpleIdentifier,
407    abstract_span: Span,
408    semicolon_span: Span,
409) -> ParseError {
410    ParseError::new(
411        "E015",
412        format!(
413            "cannot declare method `{}::{}` abstract, as `{}` class is not abstract",
414            state.named(&class),
415            method.value,
416            class,
417        ),
418        semicolon_span,
419    )
420    .error(
421        "try removing this `abstract` modifier",
422        abstract_span.position,
423        "abstract".len(),
424    )
425    .highlight(class.span.position, class.value.len())
426    .highlight(method.span.position, method.value.len())
427}
428
429pub fn constructor_in_enum(
430    state: &mut State,
431    r#enum: &SimpleIdentifier,
432    constructor: &SimpleIdentifier,
433) -> ParseError {
434    ParseError::new(
435        "E016",
436        format!(
437            "cannot declare a constructor on enum `{}`",
438            state.named(&r#enum)
439        ),
440        constructor.span,
441    )
442    .error(
443        "try removing this constructor",
444        constructor.span.position,
445        constructor.value.len(),
446    )
447    .highlight(r#enum.span.position, r#enum.value.len())
448}
449
450pub fn magic_method_in_enum(
451    state: &mut State,
452    r#enum: &SimpleIdentifier,
453    method: &SimpleIdentifier,
454) -> ParseError {
455    ParseError::new(
456        "E017",
457        format!(
458            "cannot declare magic method `{}::{}` in an enum",
459            state.named(&r#enum),
460            method.value
461        ),
462        method.span,
463    )
464    .error(
465        "try removing this magic method",
466        method.span.position,
467        method.value.len(),
468    )
469    .highlight(r#enum.span.position, r#enum.value.len())
470}
471
472pub fn missing_case_value_for_backed_enum(
473    state: &mut State,
474    r#enum: &SimpleIdentifier,
475    case: &SimpleIdentifier,
476    semicolon_span: Span,
477) -> ParseError {
478    ParseError::new(
479        "E018",
480        format!(
481            "case `{}::{}` of backed enum `{}` must have a value",
482            state.named(&r#enum),
483            case,
484            r#enum
485        ),
486        semicolon_span,
487    )
488    .error("try adding a value", semicolon_span.position, 1)
489    .highlight(case.span.position, case.value.len())
490    .highlight(r#enum.span.position, r#enum.value.len())
491}
492
493pub fn case_value_for_unit_enum(
494    state: &mut State,
495    r#enum: &SimpleIdentifier,
496    case: &SimpleIdentifier,
497    equals_span: Span,
498) -> ParseError {
499    ParseError::new(
500        "E019",
501        format!(
502            "case `{}::{}` of unit enum `{}` cannot have a value",
503            state.named(&r#enum),
504            case,
505            r#enum
506        ),
507        equals_span,
508    )
509    .error("try replacing this with `;`", equals_span.position, 1)
510    .highlight(case.span.position, case.value.len())
511    .highlight(r#enum.span.position, r#enum.value.len())
512}
513
514pub fn modifier_cannot_be_used_for_constant(modifier: String, modifier_span: Span) -> ParseError {
515    ParseError::new(
516        "E020",
517        format!("cannot use '{}' as constant modifier", modifier),
518        modifier_span,
519    )
520    .error("try removing this", modifier_span.position, modifier.len())
521    .note("only `public`, `protected`, `private`, and `final` modifiers can be used on constants")
522}
523
524pub fn modifier_cannot_be_used_for_interface_constant(
525    modifier: String,
526    modifier_span: Span,
527) -> ParseError {
528    ParseError::new(
529        "E021",
530        format!(
531            "cannot use '{}' as an interface constant modifier",
532            modifier
533        ),
534        modifier_span,
535    )
536    .error("try removing this", modifier_span.position, modifier.len())
537    .note("only `public`, and `final` modifiers can be used on interface constants")
538}
539
540pub fn modifier_cannot_be_used_for_promoted_property(
541    modifier: String,
542    modifier_span: Span,
543) -> ParseError {
544    ParseError::new(
545        "E022",
546        format!("cannot use '{}' as a promoted property modifier", modifier),
547        modifier_span,
548    )
549    .error(
550        "try removing this",
551        modifier_span.position,
552        modifier.len(),
553    )
554    .note("only `public`, `protected`, `private`, and `readonly` modifiers can be used on promoted properties")
555}
556
557pub fn modifier_cannot_be_used_for_property(modifier: String, modifier_span: Span) -> ParseError {
558    ParseError::new(
559        "E023",
560        format!("cannot use '{}' as a property modifier", modifier),
561        modifier_span,
562    )
563    .error(
564        "try removing this",
565        modifier_span.position,
566        modifier.len(),
567    )
568    .note("only `public`, `protected`, `private`, `static`, and `readonly` modifiers can be used on properties")
569}
570
571pub fn modifier_cannot_be_used_for_class(modifier: String, modifier_span: Span) -> ParseError {
572    ParseError::new(
573        "E024",
574        format!("cannot use '{}' as a class modifier", modifier),
575        modifier_span,
576    )
577    .error("try removing this", modifier_span.position, modifier.len())
578    .note("only `final`, `abstract`, and `readonly` modifiers can be used on classes")
579}
580
581pub fn modifier_cannot_be_used_for_class_method(
582    modifier: String,
583    modifier_span: Span,
584) -> ParseError {
585    ParseError::new(
586        "E025",
587        format!("cannot use '{}' as a class method modifier", modifier),
588        modifier_span,
589    )
590    .error(
591        "try removing this",
592        modifier_span.position,
593        modifier.len(),
594    )
595    .note("only `public`, `protected`, `private`, `final`, `static`, and `abstract` modifiers can be used on class methods")
596}
597
598pub fn modifier_cannot_be_used_for_enum_method(
599    modifier: String,
600    modifier_span: Span,
601) -> ParseError {
602    ParseError::new(
603        "E026",
604        format!("cannot use '{}' as an enum method modifier", modifier),
605        modifier_span,
606    )
607    .error(
608        "try removing this",
609        modifier_span.position,
610        modifier.len(),
611    )
612    .note("only `public`, `protected`, `private`, `final`, and `static` modifiers can be used on enum methods")
613}
614
615pub fn modifier_cannot_be_used_for_interface_method(
616    modifier: String,
617    modifier_span: Span,
618) -> ParseError {
619    ParseError::new(
620        "E027",
621        format!("cannot use '{}' as an interface method modifier", modifier),
622        modifier_span,
623    )
624    .error("try removing this", modifier_span.position, modifier.len())
625    .note("only `public`, and `static` modifiers can be used on interface methods")
626}
627
628pub fn final_and_abstract_modifiers_combined_for_class(
629    final_span: Span,
630    abstract_span: Span,
631) -> ParseError {
632    ParseError::new(
633        "E028",
634        "cannot declare a `final` class as `abstract`",
635        abstract_span,
636    )
637    .highlight(final_span.position, "final".len())
638    .error(
639        "try removing this",
640        abstract_span.position,
641        "abstract".len(),
642    )
643}
644
645pub fn final_and_abstract_modifiers_combined_for_class_member(
646    final_span: Span,
647    abstract_span: Span,
648) -> ParseError {
649    ParseError::new(
650        "E029",
651        "cannot declare a `final` class member as `abstract`",
652        abstract_span,
653    )
654    .highlight(final_span.position, "final".len())
655    .error(
656        "try removing this",
657        abstract_span.position,
658        "abstract".len(),
659    )
660}
661
662pub fn final_and_private_modifiers_combined_for_constant(
663    final_span: Span,
664    private_span: Span,
665) -> ParseError {
666    ParseError::new(
667        "E030",
668        "cannot declare a `private` constant as `final`",
669        final_span,
670    )
671    .highlight(private_span.position, "private".len())
672    .error("try removing this", final_span.position, "final".len())
673    .note("private constants cannot be final as they are not visible to other classes")
674}
675
676pub fn reached_unpredictable_state(span: Span) -> ParseError {
677    ParseError::new("E031", "reached unpredictable state", span).error(
678        "please report this as a bug",
679        span.position,
680        1,
681    )
682}
683
684pub fn static_property_cannot_be_readonly(
685    state: &mut State,
686    class: Option<&SimpleIdentifier>,
687    property: &SimpleVariable,
688    static_span: Span,
689    readonly_span: Span,
690) -> ParseError {
691    let error = ParseError::new(
692        "E032",
693        format!(
694            "cannot declare `readonly` property `{}::{}` as 'static'",
695            class
696                .map(|c| state.named(c))
697                .unwrap_or_else(|| "anonymous@class".to_string()),
698            property.name,
699        ),
700        static_span,
701    )
702    .highlight(property.span.position, property.name.len())
703    .highlight(readonly_span.position, "readonly".len())
704    .error("try removing this", static_span.position, "static".len());
705
706    // If the class is anonymous, we don't have a span to highlight
707    if let Some(class) = class {
708        error.highlight(class.span.position, class.value.len())
709    } else {
710        error
711    }
712}
713
714pub fn readonly_property_has_default_value(
715    state: &mut State,
716    class: Option<&SimpleIdentifier>,
717    property: &SimpleVariable,
718    readonly_span: Span,
719    equals_span: Span,
720) -> ParseError {
721    let error = ParseError::new(
722        "E033",
723        format!(
724            "readonly property `{}::{}` cannot have a default value",
725            class
726                .map(|c| state.named(c))
727                .unwrap_or_else(|| "anonymous@class".to_string()),
728            property.name,
729        ),
730        equals_span,
731    )
732    .highlight(property.span.position, property.name.len())
733    .highlight(readonly_span.position, "readonly".len())
734    .error("try removing this `=`", equals_span.position, 1);
735
736    // If the class is anonymous, we don't have a span to highlight
737    if let Some(class) = class {
738        error.highlight(class.span.position, class.value.len())
739    } else {
740        error
741    }
742}
743
744pub fn unbraced_namespace_declarations_in_braced_context(span: Span) -> ParseError {
745    ParseError::new(
746        "E034",
747        "cannot mix braced and unbraced namespace declarations",
748        span,
749    )
750    .error("try replacing this `;` with `{`", span.position, 1)
751}
752
753pub fn braced_namespace_declarations_in_unbraced_context(span: Span) -> ParseError {
754    ParseError::new(
755        "E035",
756        "cannot mix braced and unbraced namespace declarations",
757        span,
758    )
759    .error("try replacing this `{` with `;`", span.position, 1)
760}
761
762pub fn nested_namespace_declarations(span: Span) -> ParseError {
763    ParseError::new("E035", "cannot nest namespace declarations", span).error(
764        "try closing previous namespace with `}` before declaring a new one",
765        span.position,
766        1,
767    )
768}
769
770pub fn forbidden_type_used_in_property(
771    state: &mut State,
772    class: Option<&SimpleIdentifier>,
773    property: &SimpleVariable,
774    ty: Type,
775) -> ParseError {
776    let type_string = ty.to_string();
777    let type_span = ty.first_span();
778
779    let error = ParseError::new(
780        "E037".to_string(),
781        format!(
782            "property `{}::{}` cannot have type `{}`",
783            class
784                .map(|c| state.named(c))
785                .unwrap_or_else(|| "anonymous@class".to_string()),
786            property.name,
787            type_string
788        ),
789        type_span,
790    )
791    .highlight(property.span.position, property.name.len())
792    .error(
793        "try using a different type",
794        type_span.position,
795        type_string.len(),
796    )
797    .note("`void`, `never`, and `callable` types are not allowed in properties");
798
799    // If the class is anonymous, we don't have a span to highlight
800    if let Some(class) = class {
801        error.highlight(class.span.position, class.value.len())
802    } else {
803        error
804    }
805}
806
807pub fn match_expression_has_multiple_default_arms(first: Span, second: Span) -> ParseError {
808    ParseError::new(
809        "E038".to_string(),
810        "match expression cannot have more than one default arm",
811        second,
812    )
813    .highlight(first.position, "default".len())
814    .error("try removing this arm", second.position, "default".len())
815}
816
817pub fn missing_item_definition_after_attributes(
818    attributes: &Vec<AttributeGroup>,
819    current: &Token,
820) -> ParseError {
821    let mut annotations = vec![];
822
823    for attribute in attributes {
824        annotations.push(ParseErrorAnnotation {
825            r#type: ParseErrorAnnotationType::Hint,
826            message: "".to_string(),
827            position: attribute.start.position,
828            length: attribute.end.position - attribute.start.position,
829        });
830    }
831
832    annotations.push(match current.kind {
833        TokenKind::Eof => ParseErrorAnnotation {
834            r#type: ParseErrorAnnotationType::Error,
835            message: "reached end of file before an item definition".to_string(),
836            position: current.span.position,
837            length: current.value.len(),
838        },
839        _ => ParseErrorAnnotation {
840            r#type: ParseErrorAnnotationType::Error,
841            message: format!("expected an item definition, found `{}`", current.value),
842            position: current.span.position,
843            length: current.value.len(),
844        },
845    });
846
847    ParseError {
848        id: "E039".to_string(),
849        message: "missing item definition after attribute(s)".to_string(),
850        span: current.span,
851        annotations,
852        note: None,
853    }
854}
855
856pub fn nested_disjunctive_normal_form_types(span: Span) -> ParseError {
857    ParseError::new(
858        "E040".to_string(),
859        "cannot nest disjunctive normal form types",
860        span,
861    )
862    .error("try removing this", span.position, 1)
863}
864
865pub fn illegal_spread_operator_usage(span: Span) -> ParseError {
866    ParseError::new("E041".to_string(), "illegal spread operator usage", span).error(
867        "try removing this",
868        span.position,
869        3,
870    )
871}
872
873pub fn cannot_assign_reference_to_non_referencable_value(span: Span) -> ParseError {
874    ParseError::new(
875        "E042".to_string(),
876        "cannot assign reference to non-referencable value",
877        span,
878    )
879    .error("try removing this", span.position, 1)
880}
881
882pub fn mixing_keyed_and_unkeyed_list_entries(span: Span) -> ParseError {
883    ParseError::new(
884        "E043".to_string(),
885        "cannot mix keyed and un-keyed list entries",
886        span,
887    )
888    .error("", span.position, 1)
889}
890
891pub fn cannot_use_positional_argument_after_named_argument(
892    span: Span,
893    current_span: Span,
894) -> ParseError {
895    ParseError::new(
896        "E044".to_string(),
897        "cannot use positional argument after named argument",
898        span,
899    )
900    .error(
901        "try adding a name for this argument",
902        span.position,
903        current_span.position - span.position,
904    )
905}
906
907pub fn cannot_use_reserved_keyword_as_a_type_name(span: Span, keyword: String) -> ParseError {
908    ParseError::new(
909        "E045".to_string(),
910        format!("cannot use reserved keyword `{}` as a type name", keyword),
911        span,
912    )
913    .error("try using a different name", span.position, keyword.len())
914}
915
916pub fn cannot_use_reserved_keyword_as_a_goto_label(span: Span, keyword: String) -> ParseError {
917    ParseError::new(
918        "E046".to_string(),
919        format!("cannot use reserved keyword `{}` as a goto label", keyword),
920        span,
921    )
922    .error("try using a different name", span.position, keyword.len())
923}
924
925pub fn cannot_use_reserved_keyword_as_a_constant_name(span: Span, keyword: String) -> ParseError {
926    ParseError::new(
927        "E047".to_string(),
928        format!(
929            "cannot use reserved keyword `{}` as a constant name",
930            keyword
931        ),
932        span,
933    )
934    .error("try using a different name", span.position, keyword.len())
935}
936
937pub fn cannot_use_type_in_context(span: Span, ty: String) -> ParseError {
938    ParseError::new(
939        "E048".to_string(),
940        format!("cannot use type `{}` in current context", ty),
941        span,
942    )
943    .error("try using a different type", span.position, ty.len())
944}
945
946pub fn only_positional_arguments_are_accepted(span: Span, current_span: Span) -> ParseError {
947    ParseError::new(
948        "E049".to_string(),
949        "cannot use named argument, only positional arguments are accepted",
950        span,
951    )
952    .error(
953        "try changing this to a positional argument",
954        span.position,
955        current_span.position - span.position,
956    )
957}
958
959pub fn only_one_argument_is_accepted(span: Span, current_span: Span) -> ParseError {
960    ParseError::new("E050".to_string(), "only one argument are accepted", span).error(
961        "try removing this argument",
962        span.position,
963        current_span.position - span.position,
964    )
965}
966
967pub fn argument_is_required(span: Span, current_span: Span) -> ParseError {
968    ParseError::new("E051".to_string(), "argument is required", span).error(
969        "try passing an argument",
970        span.position,
971        current_span.position - span.position,
972    )
973}
974
975impl From<SyntaxError> for ParseError {
976    fn from(e: SyntaxError) -> Self {
977        Self {
978            id: "E001".to_string(),
979            message: format!("syntax error, {}", e),
980            annotations: vec![],
981            span: e.span(),
982            note: None,
983        }
984    }
985}
986
987impl Display for ParseError {
988    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
989        write!(
990            f,
991            "[{}] Error: {} on line {} column {}",
992            self.id, self.message, self.span.line, self.span.column
993        )?;
994
995        if let Some(note) = &self.note {
996            write!(f, ", Note: {}", note)?;
997        }
998
999        Ok(())
1000    }
1001}
1002
1003impl Display for ParseErrorStack {
1004    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1005        for error in &self.errors {
1006            writeln!(f, "{}", error)?;
1007        }
1008
1009        Ok(())
1010    }
1011}