use crate::diagnostic::{Diagnostic, SecondaryLabel}; use crate::error_codes::{ CLASS_NO_CONSTRUCTOR, FIELD_NO_TYPE_OR_INIT, OUTER_CLASS_FIELD_USED_IN_INIT, OUTER_CLASS_METHOD_USED_IN_INIT, SELF_CONSTRUCTOR_USED_IN_INIT, SELF_FIELD_USED_IN_INIT, SELF_METHOD_USED_IN_INIT, SYMBOL_ALREADY_DECLARED, SYMBOL_NOT_FOUND, }; use crate::source_range::SourceRange; use crate::symbol::Symbol; pub fn symbol_not_found(name: &str, source_range: &SourceRange) -> Diagnostic { Diagnostic::new( &format!("Symbol {} not found in scope.", name), source_range.start(), source_range.end(), ) .with_error_code(SYMBOL_NOT_FOUND) } pub fn field_has_no_type_or_init(name: &str, source_range: &SourceRange) -> Diagnostic { Diagnostic::new( &format!("Field {} has no declared type nor initializer.", name), source_range.start(), source_range.end(), ) .with_error_code(FIELD_NO_TYPE_OR_INIT) .with_primary_label_message("Declare a type and/or an initializer.") } pub fn cannot_reference_field_in_init(name: &str, source_range: &SourceRange) -> Diagnostic { Diagnostic::new( &format!("Cannot reference field {} during initialization.", name), source_range.start(), source_range.end(), ) .with_error_code(SELF_FIELD_USED_IN_INIT) } pub fn symbol_already_declared(already_inserted: &Symbol, would_insert: &Symbol) -> Diagnostic { let secondary_label = if let Some(source_range) = already_inserted.declared_name_source_range() { Some(SecondaryLabel::new( source_range.start(), source_range.end(), Some("Symbol already declared here.".to_string()), )) } else { None }; let diagnostic = Diagnostic::new( &format!( "Symbol {} already declared in current scope.", would_insert.declared_name() ), would_insert.declared_name_source_range().unwrap().start(), // unwrap should be okay, since this is user code would_insert.declared_name_source_range().unwrap().end(), ) .with_error_code(SYMBOL_ALREADY_DECLARED); if let Some(secondary_label) = secondary_label { diagnostic.with_secondary_labels(&[secondary_label]) } else { diagnostic } } pub fn self_constructor_used_in_init(source_range: &SourceRange) -> Diagnostic { Diagnostic::new( "Cannot call Self constructor during initialization.", source_range.start(), source_range.end(), ) .with_error_code(SELF_CONSTRUCTOR_USED_IN_INIT) } pub fn self_field_used_in_init(source_range: &SourceRange) -> Diagnostic { Diagnostic::new( "Cannot reference Self field during initialization.", source_range.start(), source_range.end(), ) .with_error_code(SELF_FIELD_USED_IN_INIT) } pub fn self_method_used_in_init(source_range: &SourceRange) -> Diagnostic { Diagnostic::new( "Cannot call Self method during initialization.", source_range.start(), source_range.end(), ) .with_error_code(SELF_METHOD_USED_IN_INIT) } pub fn outer_class_field_usage(source_range: &SourceRange) -> Diagnostic { Diagnostic::new( "Cannot reference an outer class member.", source_range.start(), source_range.end(), ) .with_error_code(OUTER_CLASS_FIELD_USED_IN_INIT) } pub fn outer_class_method_usage(source_range: &SourceRange) -> Diagnostic { Diagnostic::new( "Cannot call an outer class method.", source_range.start(), source_range.end(), ) .with_error_code(OUTER_CLASS_METHOD_USED_IN_INIT) } pub fn class_has_no_constructor(name: &str, source_range: &SourceRange) -> Diagnostic { Diagnostic::new( &format!("Class {} has no constructor.", name), source_range.start(), source_range.end(), ) .with_error_code(CLASS_NO_CONSTRUCTOR) }