From ce21d0f76fdcc5ee2530f999bb72e6120010e335 Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Tue, 14 Apr 2026 14:56:30 -0400 Subject: [PATCH 1/9] All the diagnostic creation has been updated. --- slicec/src/grammar/attributes/compress.rs | 2 +- slicec/src/grammar/attributes/mod.rs | 6 +-- .../src/grammar/attributes/sliced_format.rs | 2 +- slicec/src/parsers/comments/mod.rs | 6 +-- slicec/src/parsers/mod.rs | 14 +++--- slicec/src/parsers/preprocessor/mod.rs | 6 +-- slicec/src/parsers/slice/grammar.rs | 10 ++--- slicec/src/parsers/slice/mod.rs | 6 +-- slicec/src/patchers/comment_link_patcher.rs | 2 +- slicec/src/patchers/mod.rs | 2 +- slicec/src/patchers/type_ref_patcher.rs | 6 +-- slicec/src/utils/file_util.rs | 16 +++---- slicec/src/validators/attribute.rs | 2 +- slicec/src/validators/comments.rs | 2 +- slicec/src/validators/cycle_detection.rs | 8 ++-- slicec/src/validators/dictionary.rs | 12 ++--- slicec/src/validators/enums.rs | 18 ++++---- slicec/src/validators/identifiers.rs | 4 +- slicec/src/validators/members.rs | 4 +- slicec/src/validators/operations.rs | 8 ++-- slicec/src/validators/parameters.rs | 4 +- slicec/src/validators/structs.rs | 4 +- slicec/src/validators/type_aliases.rs | 2 +- slicec/tests/attribute_tests.rs | 44 +++++++++---------- slicec/tests/comment_tests.rs | 26 +++++------ slicec/tests/cycle_tests.rs | 42 +++++++++--------- slicec/tests/dictionaries/key_type.rs | 12 ++--- slicec/tests/dictionaries/value_type.rs | 4 +- slicec/tests/enums/container.rs | 32 +++++++------- slicec/tests/enums/mod.rs | 8 ++-- slicec/tests/files/io.rs | 4 +- slicec/tests/identifier_tests.rs | 4 +- slicec/tests/interfaces/inheritance.rs | 4 +- slicec/tests/interfaces/mod.rs | 2 +- slicec/tests/interfaces/operations.rs | 12 ++--- slicec/tests/module_tests.rs | 2 +- slicec/tests/parser_tests.rs | 6 +-- slicec/tests/preprocessor_tests.rs | 8 ++-- slicec/tests/redefinition_tests.rs | 24 +++++----- slicec/tests/scope_resolution_tests.rs | 4 +- slicec/tests/sequence_tests.rs | 2 +- slicec/tests/structs/container.rs | 4 +- slicec/tests/structs/tags.rs | 2 +- slicec/tests/tag_tests.rs | 12 ++--- slicec/tests/typealias_tests.rs | 2 +- 45 files changed, 203 insertions(+), 203 deletions(-) diff --git a/slicec/src/grammar/attributes/compress.rs b/slicec/src/grammar/attributes/compress.rs index a26fa3563..3ffb79b8c 100644 --- a/slicec/src/grammar/attributes/compress.rs +++ b/slicec/src/grammar/attributes/compress.rs @@ -20,7 +20,7 @@ impl Compress { "Args" => compress_args = true, "Return" => compress_return = true, _ => { - Diagnostic::new(Error::InvalidAttributeArgument { + Diagnostic::error(Error::InvalidAttributeArgument { directive: Self::directive().to_owned(), argument: arg.clone(), }) diff --git a/slicec/src/grammar/attributes/mod.rs b/slicec/src/grammar/attributes/mod.rs index 677bc3bc5..c7f4c034c 100644 --- a/slicec/src/grammar/attributes/mod.rs +++ b/slicec/src/grammar/attributes/mod.rs @@ -13,7 +13,7 @@ pub use oneway::*; pub use sliced_format::*; use super::Attributables; -use crate::diagnostics::{Diagnostic, Diagnostics, Error, Lint}; +use crate::diagnostics::{Diagnostic, Diagnostics, Error}; use crate::slice_file::Span; use std::ops::Range; @@ -84,7 +84,7 @@ fn report_invalid_attribute( note: Option<&str>, diagnostics: &mut Diagnostics, ) { - let mut diagnostic = Diagnostic::new(Error::InvalidAttribute { + let mut diagnostic = Diagnostic::error(Error::InvalidAttribute { directive: attribute.directive().to_owned(), }) .set_span(span); @@ -113,7 +113,7 @@ fn check_argument_count_is_within( diagnostics: &mut Diagnostics, ) { if !range.contains(&arguments.len()) { - Diagnostic::new(Error::IncorrectAttributeArgumentCount { + Diagnostic::error(Error::IncorrectAttributeArgumentCount { directive: directive.to_owned(), expected_count: range, actual_count: arguments.len(), diff --git a/slicec/src/grammar/attributes/sliced_format.rs b/slicec/src/grammar/attributes/sliced_format.rs index 0208fa9db..03b267d8f 100644 --- a/slicec/src/grammar/attributes/sliced_format.rs +++ b/slicec/src/grammar/attributes/sliced_format.rs @@ -20,7 +20,7 @@ impl SlicedFormat { "Args" => sliced_args = true, "Return" => sliced_return = true, _ => { - Diagnostic::new(Error::InvalidAttributeArgument { + Diagnostic::error(Error::InvalidAttributeArgument { directive: Self::directive().to_owned(), argument: arg.clone(), }) diff --git a/slicec/src/parsers/comments/mod.rs b/slicec/src/parsers/comments/mod.rs index e22a6b5f4..6de8c9fc5 100644 --- a/slicec/src/parsers/comments/mod.rs +++ b/slicec/src/parsers/comments/mod.rs @@ -24,7 +24,7 @@ fn construct_lint_from(parse_error: ParseError, file_name: &str) -> Diagnostic { let converted = Lint::MalformedDocComment { message: parse_error_kind.to_string(), }; - Diagnostic::new(converted).set_span(&Span::new(start, end, file_name)) + Diagnostic::lint(converted).set_span(&Span::new(start, end, file_name)) } // The parser encountered a token that didn't fit any grammar rule. @@ -34,13 +34,13 @@ fn construct_lint_from(parse_error: ParseError, file_name: &str) -> Diagnostic { } => { // TODO: should use Display like in Slice parser. let message = generate_message(&expected, token_kind); - Diagnostic::new(Lint::MalformedDocComment { message }).set_span(&Span::new(start, end, file_name)) + Diagnostic::lint(Lint::MalformedDocComment { message }).set_span(&Span::new(start, end, file_name)) } // The parser hit EOF in the middle of a grammar rule. ParseError::UnrecognizedEof { location, expected } => { let message = generate_message(&expected, "EOF"); - Diagnostic::new(Lint::MalformedDocComment { message }).set_span(&Span::new(location, location, file_name)) + Diagnostic::lint(Lint::MalformedDocComment { message }).set_span(&Span::new(location, location, file_name)) } _ => unreachable!("impossible error encountered in comment parser: {parse_error:?}"), diff --git a/slicec/src/parsers/mod.rs b/slicec/src/parsers/mod.rs index 6fa800476..fd7c4ce4a 100644 --- a/slicec/src/parsers/mod.rs +++ b/slicec/src/parsers/mod.rs @@ -2,16 +2,16 @@ //! TODO write a comment about how parsing works in Slice. -// We only export the parsers and keep all the other logic private. -pub use self::comments::parser::CommentParser; -pub use self::preprocessor::parser::Preprocessor; -pub use self::slice::parser::Parser; - mod comments; mod common; mod preprocessor; mod slice; +// We only export the parsers and keep all the other logic private. +pub use self::comments::parser::CommentParser; +pub use self::preprocessor::parser::Preprocessor; +pub use self::slice::parser::Parser; + use crate::ast::Ast; use crate::compilation_state::CompilationState; use crate::diagnostics::{Diagnostic, Diagnostics, Error}; @@ -25,7 +25,7 @@ pub fn parse_files(state: &mut CompilationState, symbols: &HashSet) { parse_file(file, &mut state.ast, &mut diagnostics, symbols.clone()); // Store any diagnostics that were emitted during parsing. - state.diagnostics.extend(diagnostics); + state.diagnostics.extend(diagnostics.into_inner()); } } @@ -40,7 +40,7 @@ fn parse_file(file: &mut SliceFile, ast: &mut Ast, diagnostics: &mut Diagnostics // Issue a syntax error if the user had definitions but forgot to declare a module. if !definitions.is_empty() && module.is_none() { - Diagnostic::new(Error::Syntax { + Diagnostic::error(Error::Syntax { // TODO improve this message, see: #348 message: "module declaration is required".to_owned(), }) diff --git a/slicec/src/parsers/preprocessor/mod.rs b/slicec/src/parsers/preprocessor/mod.rs index b29cad3fd..174ff6568 100644 --- a/slicec/src/parsers/preprocessor/mod.rs +++ b/slicec/src/parsers/preprocessor/mod.rs @@ -27,7 +27,7 @@ fn construct_error_from(parse_error: ParseError, file_name: &str) -> Diagnostic let converted = Error::Syntax { message: parse_error_kind.to_string(), }; - Diagnostic::new(converted).set_span(&Span::new(start, end, file_name)) + Diagnostic::error(converted).set_span(&Span::new(start, end, file_name)) } // The parser encountered a token that didn't fit any grammar rule. @@ -36,13 +36,13 @@ fn construct_error_from(parse_error: ParseError, file_name: &str) -> Diagnostic expected, } => { let message = generate_message(&expected, token_kind); - Diagnostic::new(Error::Syntax { message }).set_span(&Span::new(start, end, file_name)) + Diagnostic::error(Error::Syntax { message }).set_span(&Span::new(start, end, file_name)) } // The parser hit EOF in the middle of a grammar rule. ParseError::UnrecognizedEof { location, expected } => { let message = generate_message(&expected, "EOF"); - Diagnostic::new(Error::Syntax { message }).set_span(&Span::new(location, location, file_name)) + Diagnostic::error(Error::Syntax { message }).set_span(&Span::new(location, location, file_name)) } // Only the built-in lexer emits 'InvalidToken' errors. We use our own lexer so this is impossible. diff --git a/slicec/src/parsers/slice/grammar.rs b/slicec/src/parsers/slice/grammar.rs index 182b7fb30..c524fa336 100644 --- a/slicec/src/parsers/slice/grammar.rs +++ b/slicec/src/parsers/slice/grammar.rs @@ -67,7 +67,7 @@ fn construct_module( let error = Error::Syntax { message: "doc comments cannot be applied to modules".to_owned(), }; - Diagnostic::new(error).set_span(&span).push_into(parser.diagnostics); + Diagnostic::error(error).set_span(&span).push_into(parser.diagnostics); } let module_ptr = OwnedPtr::new(Module { @@ -203,7 +203,7 @@ fn construct_parameter( span: Span, ) -> OwnedPtr { if !raw_comment.is_empty() { - Diagnostic::new(Error::Syntax { + Diagnostic::error(Error::Syntax { message: "doc comments cannot be applied to parameters".to_owned(), }) .set_span(&span) @@ -251,7 +251,7 @@ fn construct_single_return_type( fn check_return_tuple(parser: &mut Parser, return_tuple: &[OwnedPtr], span: Span) { if return_tuple.len() < 2 { - let diagnostic = Diagnostic::new(Error::ReturnTuplesMustContainAtLeastTwoElements).set_span(&span); + let diagnostic = Diagnostic::error(Error::ReturnTuplesMustContainAtLeastTwoElements).set_span(&span); diagnostic.push_into(parser.diagnostics); } } @@ -454,7 +454,7 @@ fn try_parse_integer(parser: &mut Parser, s: &str, span: Span) -> Integer IntErrorKind::InvalidDigit => Error::InvalidIntegerLiteral { base }, _ => Error::IntegerLiteralOverflows, }; - Diagnostic::new(e).set_span(&span).push_into(parser.diagnostics); + Diagnostic::error(e).set_span(&span).push_into(parser.diagnostics); 0 // Dummy value } }; @@ -465,7 +465,7 @@ fn try_parse_integer(parser: &mut Parser, s: &str, span: Span) -> Integer fn parse_tag_value(parser: &mut Parser, i: Integer) -> Integer { // Verify that the provided integer is a valid tag id. if !RangeInclusive::new(0, i32::MAX as i128).contains(&i.value) { - let diagnostic = Diagnostic::new(Error::TagValueOutOfBounds).set_span(&i.span); + let diagnostic = Diagnostic::error(Error::TagValueOutOfBounds).set_span(&i.span); diagnostic.push_into(parser.diagnostics); } diff --git a/slicec/src/parsers/slice/mod.rs b/slicec/src/parsers/slice/mod.rs index 1bdb0d70d..05fe961a9 100644 --- a/slicec/src/parsers/slice/mod.rs +++ b/slicec/src/parsers/slice/mod.rs @@ -24,7 +24,7 @@ fn construct_error_from(parse_error: ParseError, file_name: &str) -> Diagnostic let converted = Error::Syntax { message: parse_error_kind.to_string(), }; - Diagnostic::new(converted).set_span(&Span::new(start, end, file_name)) + Diagnostic::error(converted).set_span(&Span::new(start, end, file_name)) } // The parser encountered a token that didn't fit any grammar rule. @@ -33,13 +33,13 @@ fn construct_error_from(parse_error: ParseError, file_name: &str) -> Diagnostic expected, } => { let message = generate_message(&expected, token_kind); - Diagnostic::new(Error::Syntax { message }).set_span(&Span::new(start, end, file_name)) + Diagnostic::error(Error::Syntax { message }).set_span(&Span::new(start, end, file_name)) } // The parser hit EOF in the middle of a grammar rule. ParseError::UnrecognizedEof { location, expected } => { let message = generate_message(&expected, "EOF"); - Diagnostic::new(Error::Syntax { message }).set_span(&Span::new(location, location, file_name)) + Diagnostic::error(Error::Syntax { message }).set_span(&Span::new(location, location, file_name)) } _ => unreachable!("impossible error encountered in Slice parser: '{parse_error:?}'"), diff --git a/slicec/src/patchers/comment_link_patcher.rs b/slicec/src/patchers/comment_link_patcher.rs index 7ec2776cf..a92bd6983 100644 --- a/slicec/src/patchers/comment_link_patcher.rs +++ b/slicec/src/patchers/comment_link_patcher.rs @@ -115,7 +115,7 @@ impl CommentLinkPatcher<'_> { self.link_patches.push_back(match result { Ok(ptr) => Some(ptr), Err(message) => { - Diagnostic::new(Lint::BrokenDocLink { message }) + Diagnostic::lint(Lint::BrokenDocLink { message }) .set_span(identifier.span()) .set_scope(commentable.parser_scoped_identifier()) .push_into(self.diagnostics); diff --git a/slicec/src/patchers/mod.rs b/slicec/src/patchers/mod.rs index 5ebe47c07..e493b93ca 100644 --- a/slicec/src/patchers/mod.rs +++ b/slicec/src/patchers/mod.rs @@ -45,7 +45,7 @@ macro_rules! patch_attributes { // If the directive starts with the provided prefix, but didn't match a known attribute. let directive_prefix = directive.split_once("::").map_or("", |(p, _)| p); if $prefix == directive_prefix { - Diagnostic::new(Error::UnknownAttribute { + Diagnostic::error(Error::UnknownAttribute { directive: directive.to_owned(), }) .set_span(attribute.span()) diff --git a/slicec/src/patchers/type_ref_patcher.rs b/slicec/src/patchers/type_ref_patcher.rs index a5dd30d63..1a46a79e4 100644 --- a/slicec/src/patchers/type_ref_patcher.rs +++ b/slicec/src/patchers/type_ref_patcher.rs @@ -190,7 +190,7 @@ impl TypeRefPatcher<'_> { is_concrete, }, }; - Diagnostic::new(mapped_error) + Diagnostic::error(mapped_error) .set_span(identifier.span()) .push_into(self.diagnostics); None @@ -207,7 +207,7 @@ impl TypeRefPatcher<'_> { // only check the first argument. If it's present, we attach it to the lint message. let identifier = entity.identifier().to_owned(); let reason = deprecated.reason.clone(); - Diagnostic::new(Lint::Deprecated { identifier, reason }) + Diagnostic::lint(Lint::Deprecated { identifier, reason }) .set_span(type_ref.span()) .set_scope(type_ref.parser_scope()) .add_note( @@ -243,7 +243,7 @@ impl TypeRefPatcher<'_> { // an error for it. This check makes sure we don't report errors for type aliases that aren't cyclic, // but use another type-alias which is. In this case, the chain contains it, but it won't be the first. if type_alias_chain.first() == Some(&type_alias_id) { - Diagnostic::new(Error::SelfReferentialTypeAliasNeedsConcreteType { + Diagnostic::error(Error::SelfReferentialTypeAliasNeedsConcreteType { identifier: current_type_alias.module_scoped_identifier(), }) .set_span(current_type_alias.span()) diff --git a/slicec/src/utils/file_util.rs b/slicec/src/utils/file_util.rs index cc2a7e7d4..b42197f13 100644 --- a/slicec/src/utils/file_util.rs +++ b/slicec/src/utils/file_util.rs @@ -42,7 +42,7 @@ fn remove_duplicate_file_paths(file_paths: Vec, diagnostics: &mut Diag for file_path in file_paths { if deduped_file_paths.contains(&file_path) { let lint = Lint::DuplicateFile { path: file_path.path }; - Diagnostic::new(lint).push_into(diagnostics); + Diagnostic::lint(lint).push_into(diagnostics); } else { deduped_file_paths.push(file_path); } @@ -73,7 +73,7 @@ pub fn resolve_files_from(options: &SliceOptions, diagnostics: &mut Diagnostics) for file_path in file_paths { match fs::read_to_string(&file_path.path) { Ok(raw_text) => files.push(SliceFile::new(file_path.path, raw_text, file_path.is_source)), - Err(error) => Diagnostic::new(Error::IO { + Err(error) => Diagnostic::error(Error::IO { action: "read", path: file_path.path, error, @@ -94,7 +94,7 @@ fn find_slice_files(paths: &[String], are_source_files: bool, diagnostics: &mut // If the path does not exist, report an error and continue. if !path_buf.exists() { - Diagnostic::new(Error::IO { + Diagnostic::error(Error::IO { action: "read", path: path.to_owned(), error: io::ErrorKind::NotFound.into(), @@ -110,7 +110,7 @@ fn find_slice_files(paths: &[String], are_source_files: bool, diagnostics: &mut io::ErrorKind::InvalidFilename, "Slice files must end with a '.slice' extension", ); - Diagnostic::new(Error::IO { + Diagnostic::error(Error::IO { action: "read", path: path.to_owned(), error: io_error, @@ -126,7 +126,7 @@ fn find_slice_files(paths: &[String], are_source_files: bool, diagnostics: &mut io::ErrorKind::InvalidFilename, "Expected a Slice file but found a directory.", ); - Diagnostic::new(Error::IO { + Diagnostic::error(Error::IO { action: "read", path: path.to_owned(), error: io_error, @@ -144,7 +144,7 @@ fn find_slice_files(paths: &[String], are_source_files: bool, diagnostics: &mut .filter_map(|path| match FilePath::try_create(&path, are_source_files) { Ok(file_path) => Some(file_path), Err(error) => { - Diagnostic::new(Error::IO { + Diagnostic::error(Error::IO { action: "read", path, error, @@ -162,7 +162,7 @@ fn find_slice_files_in_path(path: PathBuf, diagnostics: &mut Diagnostics) -> Vec // Recurse into the directory. match find_slice_files_in_directory(&path, diagnostics) { Ok(child_paths) => paths.extend(child_paths), - Err(error) => Diagnostic::new(Error::IO { + Err(error) => Diagnostic::error(Error::IO { action: "read", path: path.display().to_string(), error, @@ -188,7 +188,7 @@ fn find_slice_files_in_directory(path: &Path, diagnostics: &mut Diagnostics) -> Ok(child) => paths.extend(find_slice_files_in_path(child.path(), diagnostics)), Err(error) => { // If we cannot read the directory entry, report an error and continue. - Diagnostic::new(Error::IO { + Diagnostic::error(Error::IO { action: "read", path: path.display().to_string(), error, diff --git a/slicec/src/validators/attribute.rs b/slicec/src/validators/attribute.rs index fbd9f9b47..b0f89ab36 100644 --- a/slicec/src/validators/attribute.rs +++ b/slicec/src/validators/attribute.rs @@ -29,7 +29,7 @@ pub fn validate_repeated_attributes(attributes: &[&Attribute], diagnostics: &mut match first_attribute_occurrence.entry(directive) { Occupied(entry) => { - Diagnostic::new(Error::AttributeIsNotRepeatable { + Diagnostic::error(Error::AttributeIsNotRepeatable { directive: directive.to_owned(), }) .set_span(span) diff --git a/slicec/src/validators/comments.rs b/slicec/src/validators/comments.rs index e1f837bd8..a5eadd191 100644 --- a/slicec/src/validators/comments.rs +++ b/slicec/src/validators/comments.rs @@ -51,7 +51,7 @@ fn report_only_operation_error( _ => unreachable!("'report_only_operation_error' was called with unsupported tag '{tag_kind}'"), }; - Diagnostic::new(Lint::IncorrectDocComment { + Diagnostic::lint(Lint::IncorrectDocComment { message: format!("comment has a '{tag_kind}' tag, but only operations can {action_phrase}"), }) .set_span(&(tag.span() + message_span)) diff --git a/slicec/src/validators/cycle_detection.rs b/slicec/src/validators/cycle_detection.rs index f68d0f6a6..bec6112c3 100644 --- a/slicec/src/validators/cycle_detection.rs +++ b/slicec/src/validators/cycle_detection.rs @@ -147,10 +147,10 @@ impl<'a> CycleDetector<'a> { let cycle_notes = self.dependency_stack.iter().map(|(_, field)| Self::get_note_for(field)); // Report the error. - Diagnostic::new(Error::InfiniteSizeCycle { type_id, cycle }) - .set_span(type_being_checked.1.span()) - .extend_notes(cycle_notes) - .push_into(self.diagnostics); + let mut error = Diagnostic::error(Error::InfiniteSizeCycle { type_id, cycle }); + error = error.set_span(type_being_checked.1.span()); + error.notes = cycle_notes.collect(); + self.diagnostics.push(error); } fn get_note_for(field: &Field) -> Note { diff --git a/slicec/src/validators/dictionary.rs b/slicec/src/validators/dictionary.rs index 63ba080b6..cc204d9c3 100644 --- a/slicec/src/validators/dictionary.rs +++ b/slicec/src/validators/dictionary.rs @@ -16,7 +16,7 @@ fn has_allowed_key_type(dictionary: &Dictionary, diagnostics: &mut Diagnostics) fn check_dictionary_key_type(type_ref: &TypeRef) -> Option { // Optional types cannot be used as dictionary keys. if type_ref.is_optional { - return Some(Diagnostic::new(Error::KeyMustBeNonOptional).set_span(type_ref.span())); + return Some(Diagnostic::error(Error::KeyMustBeNonOptional).set_span(type_ref.span())); } let definition = type_ref.definition(); @@ -24,7 +24,7 @@ fn check_dictionary_key_type(type_ref: &TypeRef) -> Option { Types::Struct(struct_def) => { // Only compact structs can be used for dictionary keys. if !struct_def.is_compact { - return Some(Diagnostic::new(Error::StructKeyMustBeCompact).set_span(type_ref.span())); + return Some(Diagnostic::error(Error::StructKeyMustBeCompact).set_span(type_ref.span())); } // Check that all the fields of the struct are also valid key types. @@ -35,14 +35,14 @@ fn check_dictionary_key_type(type_ref: &TypeRef) -> Option { .filter_map(|field| check_dictionary_key_type(field.data_type())) .collect::>(); if !errors.is_empty() { - let mut error = Diagnostic::new(Error::StructKeyContainsDisallowedType { + let mut error = Diagnostic::error(Error::StructKeyContainsDisallowedType { struct_identifier: struct_def.identifier().to_owned(), }) .set_span(type_ref.span()); // Convert each error into a note and add it to the struct key error. for e in errors { - error = error.add_note(e.message(), e.span()); + error = error.add_note(e.message(), e.span.as_ref()); } return Some(error); } @@ -52,7 +52,7 @@ fn check_dictionary_key_type(type_ref: &TypeRef) -> Option { // Only enums with underlying types can be used as dictionary keys. Fields aren't allowed. Types::Enum(enum_def) => { if enum_def.underlying.is_none() { - let error = Diagnostic::new(Error::KeyTypeNotSupported { + let error = Diagnostic::error(Error::KeyTypeNotSupported { kind: formatted_kind(definition), }) .set_span(type_ref.span()) @@ -73,7 +73,7 @@ fn check_dictionary_key_type(type_ref: &TypeRef) -> Option { if !is_valid { return Some( - Diagnostic::new(Error::KeyTypeNotSupported { + Diagnostic::error(Error::KeyTypeNotSupported { kind: formatted_kind(definition), }) .set_span(type_ref.span()), diff --git a/slicec/src/validators/enums.rs b/slicec/src/validators/enums.rs index 0abb65d9f..5856cc2fd 100644 --- a/slicec/src/validators/enums.rs +++ b/slicec/src/validators/enums.rs @@ -33,7 +33,7 @@ fn backing_type_bounds(enum_def: &Enum, diagnostics: &mut Diagnostics) { min, max, }; - Diagnostic::new(error) + Diagnostic::error(error) .set_span(enumerator.span()) .push_into(diagnostics); }); @@ -57,7 +57,7 @@ fn backing_type_bounds(enum_def: &Enum, diagnostics: &mut Diagnostics) { fn allowed_underlying_types(enum_def: &Enum, diagnostics: &mut Diagnostics) { if let Some(underlying_type) = &enum_def.underlying { if !underlying_type.is_integral() { - Diagnostic::new(Error::EnumUnderlyingTypeNotSupported { + Diagnostic::error(Error::EnumUnderlyingTypeNotSupported { enum_identifier: enum_def.identifier().to_owned(), kind: Some(underlying_type.definition().kind().to_owned()), }) @@ -74,7 +74,7 @@ fn enumerator_values_are_unique(enum_def: &Enum, diagnostics: &mut Diagnostics) // If the value is already in the map, another enumerator already used it. Get that enumerator from the map // and report an error. Otherwise add the enumerator and its value to the map. if let Some(alt_enum) = value_to_enumerator_map.get(&enumerator.value()) { - Diagnostic::new(Error::DuplicateEnumeratorValue { + Diagnostic::error(Error::DuplicateEnumeratorValue { enumerator_value: enumerator.value(), }) .set_span(enumerator.span()) @@ -93,7 +93,7 @@ fn enumerator_values_are_unique(enum_def: &Enum, diagnostics: &mut Diagnostics) fn underlying_type_cannot_be_optional(enum_def: &Enum, diagnostics: &mut Diagnostics) { if let Some(ref typeref) = enum_def.underlying { if typeref.is_optional { - Diagnostic::new(Error::CannotUseOptionalUnderlyingType { + Diagnostic::error(Error::CannotUseOptionalUnderlyingType { enum_identifier: enum_def.identifier().to_owned(), }) .set_span(enum_def.span()) @@ -105,7 +105,7 @@ fn underlying_type_cannot_be_optional(enum_def: &Enum, diagnostics: &mut Diagnos /// Validate that a checked enum must not be empty. fn nonempty_if_checked(enum_def: &Enum, diagnostics: &mut Diagnostics) { if !enum_def.is_unchecked && enum_def.enumerators.is_empty() { - Diagnostic::new(Error::MustContainEnumerators { + Diagnostic::error(Error::MustContainEnumerators { enum_identifier: enum_def.identifier().to_owned(), }) .set_span(enum_def.span()) @@ -120,7 +120,7 @@ fn cannot_contain_fields(enum_def: &Enum, diagnostics: &mut Diagnostics) { for enumerator in enum_def.enumerators() { if enumerator.fields.is_some() { - Diagnostic::new(Error::EnumeratorCannotContainFields { + Diagnostic::error(Error::EnumeratorCannotContainFields { enumerator_identifier: enumerator.identifier().to_owned(), }) .set_span(enumerator.span()) @@ -137,7 +137,7 @@ fn cannot_contain_fields(enum_def: &Enum, diagnostics: &mut Diagnostics) { fn check_compact_modifier(enum_def: &Enum, diagnostics: &mut Diagnostics) { if enum_def.is_compact { if let Some(underlying) = &enum_def.underlying { - Diagnostic::new(Error::CannotBeCompact { + Diagnostic::error(Error::CannotBeCompact { kind: enum_def.kind(), identifier: enum_def.identifier().to_owned(), }) @@ -150,7 +150,7 @@ fn check_compact_modifier(enum_def: &Enum, diagnostics: &mut Diagnostics) { } if enum_def.is_unchecked { - Diagnostic::new(Error::CannotBeCompact { + Diagnostic::error(Error::CannotBeCompact { kind: enum_def.kind(), identifier: enum_def.identifier().to_owned(), }) @@ -170,7 +170,7 @@ fn compact_enums_cannot_contain_tags(enum_def: &Enum, diagnostics: &mut Diagnost for enumerator in enum_def.enumerators() { for field in enumerator.fields() { if field.is_tagged() { - Diagnostic::new(Error::CompactTypeCannotContainTaggedFields { kind: enum_def.kind() }) + Diagnostic::error(Error::CompactTypeCannotContainTaggedFields { kind: enum_def.kind() }) .set_span(field.span()) .add_note( format!("enum '{}' is declared compact here", enum_def.identifier()), diff --git a/slicec/src/validators/identifiers.rs b/slicec/src/validators/identifiers.rs index 3a5933670..420e9a07d 100644 --- a/slicec/src/validators/identifiers.rs +++ b/slicec/src/validators/identifiers.rs @@ -27,7 +27,7 @@ fn check_for_shadowing( for identifier in identifiers { for inherited_identifier in &inherited_identifiers { if identifier.value == inherited_identifier.value { - Diagnostic::new(Error::Shadows { + Diagnostic::error(Error::Shadows { identifier: identifier.value.clone(), }) .set_span(identifier.span()) @@ -118,7 +118,7 @@ impl<'a> RedefinitionChecker<'a> { } fn report_redefinition_error(&mut self, new: &dyn NamedSymbol, original: &dyn NamedSymbol) { - Diagnostic::new(Error::Redefinition { + Diagnostic::error(Error::Redefinition { identifier: new.identifier().to_owned(), }) .set_span(new.raw_identifier().span()) diff --git a/slicec/src/validators/members.rs b/slicec/src/validators/members.rs index 99138f847..cbef6a17e 100644 --- a/slicec/src/validators/members.rs +++ b/slicec/src/validators/members.rs @@ -17,7 +17,7 @@ fn tags_are_unique(members: Vec<&impl Member>, diagnostics: &mut Diagnostics) { sorted_tagged_members.sort_by_key(|member| member.tag().expect("tagged member has no tag!")); sorted_tagged_members.windows(2).for_each(|window| { if window[0].tag() == window[1].tag() { - Diagnostic::new(Error::CannotHaveDuplicateTag { + Diagnostic::error(Error::CannotHaveDuplicateTag { identifier: window[1].identifier().to_owned(), }) .set_span(window[1].span()) @@ -41,7 +41,7 @@ fn tags_have_optional_types(members: Vec<&impl Member>, diagnostics: &mut Diagno // Validate that tagged members are optional. for member in tagged_members { if !member.data_type().is_optional { - Diagnostic::new(Error::TaggedMemberMustBeOptional { + Diagnostic::error(Error::TaggedMemberMustBeOptional { identifier: member.identifier().to_owned(), }) .set_span(member.span()) diff --git a/slicec/src/validators/operations.rs b/slicec/src/validators/operations.rs index 49a4d56c2..a20aa2212 100644 --- a/slicec/src/validators/operations.rs +++ b/slicec/src/validators/operations.rs @@ -16,7 +16,7 @@ fn validate_param_tags(comment: &DocComment, operation: &Operation, diagnostics: for param_tag in &comment.params { let tag_identifier = param_tag.identifier.value.as_str(); if !parameters.contains(&tag_identifier) { - Diagnostic::new(Lint::IncorrectDocComment { + Diagnostic::lint(Lint::IncorrectDocComment { message: format!( "comment has a 'param' tag for '{tag_identifier}', but operation '{}' has no parameter with that name", operation.identifier(), @@ -49,7 +49,7 @@ fn validate_returns_tags_for_operation_with_no_return_type( diagnostics: &mut Diagnostics, ) { for returns_tag in returns_tags { - Diagnostic::new(Lint::IncorrectDocComment { + Diagnostic::lint(Lint::IncorrectDocComment { message: format!( "comment has a 'returns' tag, but operation '{}' does not return anything", operation.identifier(), @@ -68,7 +68,7 @@ fn validate_returns_tags_for_operation_with_single_return( ) { for returns_tag in returns_tags { if let Some(tag_identifier) = &returns_tag.identifier { - Diagnostic::new(Lint::IncorrectDocComment { + Diagnostic::lint(Lint::IncorrectDocComment { message: format!( "comment has a 'returns' tag for '{}', but operation '{}' doesn't return anything with that name", &tag_identifier.value, @@ -99,7 +99,7 @@ fn validate_returns_tags_for_operation_with_return_tuple( if let Some(tag_identifier) = &returns_tag.identifier { let tag_identifier = tag_identifier.value.as_str(); if !return_members.contains(&tag_identifier) { - Diagnostic::new(Lint::IncorrectDocComment { + Diagnostic::lint(Lint::IncorrectDocComment { message: format!( "comment has a 'returns' tag for '{tag_identifier}', but operation '{}' doesn't return anything with that name", operation.identifier(), diff --git a/slicec/src/validators/parameters.rs b/slicec/src/validators/parameters.rs index 9245f64fd..73c99889f 100644 --- a/slicec/src/validators/parameters.rs +++ b/slicec/src/validators/parameters.rs @@ -15,7 +15,7 @@ fn at_most_one_stream_parameter(members: &[&Parameter], diagnostics: &mut Diagno .split_last() // Split at the last element, which is the one we do not want to report an error for. .unwrap().1 // All members before the split. Safe to unwrap since we know there are at least two members. .iter() - .for_each(|m| Diagnostic::new(Error::MultipleStreamedMembers).set_span(m.span()).push_into(diagnostics)); + .for_each(|m| Diagnostic::error(Error::MultipleStreamedMembers).set_span(m.span()).push_into(diagnostics)); } } @@ -26,7 +26,7 @@ fn stream_parameter_is_last(members: &[&Parameter], diagnostics: &mut Diagnostic .into_iter() .filter(|m| m.is_streamed) .for_each(|m| { - Diagnostic::new(Error::StreamedMembersMustBeLast { parameter_identifier: m.identifier().to_owned() }) + Diagnostic::error(Error::StreamedMembersMustBeLast { parameter_identifier: m.identifier().to_owned() }) .set_span(m.span()) .push_into(diagnostics); }); diff --git a/slicec/src/validators/structs.rs b/slicec/src/validators/structs.rs index 4edcf15b7..c704a84ef 100644 --- a/slicec/src/validators/structs.rs +++ b/slicec/src/validators/structs.rs @@ -10,7 +10,7 @@ pub fn validate_struct(struct_def: &Struct, diagnostics: &mut Diagnostics) { fn validate_compact_struct_not_empty(struct_def: &Struct, diagnostics: &mut Diagnostics) { // Compact structs must be non-empty. if struct_def.is_compact && struct_def.fields().is_empty() { - Diagnostic::new(Error::CompactStructCannotBeEmpty) + Diagnostic::error(Error::CompactStructCannotBeEmpty) .set_span(struct_def.span()) .push_into(diagnostics); } @@ -21,7 +21,7 @@ fn compact_structs_cannot_contain_tags(struct_def: &Struct, diagnostics: &mut Di if struct_def.is_compact { for field in struct_def.fields() { if field.is_tagged() { - Diagnostic::new(Error::CompactTypeCannotContainTaggedFields { kind: struct_def.kind() }) + Diagnostic::error(Error::CompactTypeCannotContainTaggedFields { kind: struct_def.kind() }) .set_span(field.span()) .add_note( format!("struct '{}' is declared compact here", struct_def.identifier()), diff --git a/slicec/src/validators/type_aliases.rs b/slicec/src/validators/type_aliases.rs index f59ebcec3..a0cbcda07 100644 --- a/slicec/src/validators/type_aliases.rs +++ b/slicec/src/validators/type_aliases.rs @@ -9,7 +9,7 @@ pub fn validate_type_alias(type_alias: &TypeAlias, diagnostics: &mut Diagnostics fn type_aliases_cannot_be_optional(type_alias: &TypeAlias, diagnostics: &mut Diagnostics) { if type_alias.underlying.is_optional { - Diagnostic::new(Error::TypeAliasOfOptional) + Diagnostic::error(Error::TypeAliasOfOptional) .set_span(type_alias.span()) .add_note( "try removing the trailing `?` modifier from its definition", diff --git a/slicec/tests/attribute_tests.rs b/slicec/tests/attribute_tests.rs index 8006acb55..ddd694c65 100644 --- a/slicec/tests/attribute_tests.rs +++ b/slicec/tests/attribute_tests.rs @@ -43,7 +43,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::InvalidAttributeArgument { + let expected = Diagnostic::error(Error::InvalidAttributeArgument { directive: "allow".to_owned(), argument: "Fake".to_owned(), }); @@ -78,7 +78,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::IncorrectAttributeArgumentCount { + let expected = Diagnostic::error(Error::IncorrectAttributeArgumentCount { directive: "allow".to_owned(), expected_count: 1..usize::MAX, actual_count: 0, @@ -113,14 +113,14 @@ mod attributes { // Assert let mut all_lints = vec![ - Diagnostic::new(Lint::Deprecated { + Diagnostic::lint(Lint::Deprecated { identifier: "S".to_owned(), reason: Some("test".to_owned()), }), - Diagnostic::new(Lint::BrokenDocLink { + Diagnostic::lint(Lint::BrokenDocLink { message: "no element named 'fake' exists in scope".to_owned(), }), - Diagnostic::new(Lint::IncorrectDocComment { + Diagnostic::lint(Lint::IncorrectDocComment { message: "comment has a 'returns' tag, but only operations can return".to_owned(), }), ]; @@ -183,7 +183,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::InvalidAttributeArgument { + let expected = Diagnostic::error(Error::InvalidAttributeArgument { directive: "slicedFormat".to_owned(), argument: "Foo".to_owned(), }) @@ -208,7 +208,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::InvalidAttribute { + let expected = Diagnostic::error(Error::InvalidAttribute { directive: "slicedFormat".to_owned(), }) .set_span(&Span::new((4, 18).into(), (4, 36).into(), "string-0")) @@ -233,7 +233,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::IncorrectAttributeArgumentCount { + let expected = Diagnostic::error(Error::IncorrectAttributeArgumentCount { directive: "slicedFormat".to_owned(), expected_count: 1..usize::MAX, actual_count: 0, @@ -278,7 +278,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::InvalidAttribute { + let expected = Diagnostic::error(Error::InvalidAttribute { directive: "deprecated".to_owned(), }) .set_span(&Span::new((5, 25).into(), (5, 35).into(), "string-0")) @@ -329,7 +329,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Lint::Deprecated { + let expected = Diagnostic::lint(Lint::Deprecated { identifier: "Bar".to_owned(), reason: None, }); @@ -350,7 +350,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::InvalidAttribute { + let expected = Diagnostic::error(Error::InvalidAttribute { directive: "deprecated".to_owned(), }); @@ -375,7 +375,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Lint::Deprecated { + let expected = Diagnostic::lint(Lint::Deprecated { identifier: "A".to_owned(), reason: Some("Message here".to_owned()), }); @@ -398,7 +398,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Lint::Deprecated { + let expected = Diagnostic::lint(Lint::Deprecated { identifier: "A".to_owned(), reason: None, }); @@ -444,7 +444,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::InvalidAttributeArgument { + let expected = Diagnostic::error(Error::InvalidAttributeArgument { directive: "compress".to_owned(), argument: "Foo".to_owned(), }) @@ -469,7 +469,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::InvalidAttribute { + let expected = Diagnostic::error(Error::InvalidAttribute { directive: "compress".to_owned(), }) .set_span(&Span::new((4, 18).into(), (4, 32).into(), "string-0")) @@ -494,7 +494,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::IncorrectAttributeArgumentCount { + let expected = Diagnostic::error(Error::IncorrectAttributeArgumentCount { directive: "compress".to_owned(), expected_count: 1..usize::MAX, actual_count: 0, @@ -521,7 +521,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::AttributeIsNotRepeatable { + let expected = Diagnostic::error(Error::AttributeIsNotRepeatable { directive: "compress".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -541,7 +541,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::InvalidAttribute { + let expected = Diagnostic::error(Error::InvalidAttribute { directive: "oneway".to_owned(), }); @@ -562,7 +562,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); - let expected = Diagnostic::new(Error::InvalidAttribute { + let expected = Diagnostic::error(Error::InvalidAttribute { directive: "deprecated".to_owned(), }); @@ -582,7 +582,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); - let expected = Diagnostic::new(Error::InvalidAttribute { + let expected = Diagnostic::error(Error::InvalidAttribute { directive: attribute.to_owned(), }); @@ -740,7 +740,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::UnknownAttribute { + let expected = Diagnostic::error(Error::UnknownAttribute { directive: directive.to_owned(), }); @@ -763,7 +763,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Syntax { + let expected = Diagnostic::error(Error::Syntax { message: format!("expected 'identifier', but found '{found}'"), }); diff --git a/slicec/tests/comment_tests.rs b/slicec/tests/comment_tests.rs index 8b18133b1..2f4a7f1b2 100644 --- a/slicec/tests/comment_tests.rs +++ b/slicec/tests/comment_tests.rs @@ -166,7 +166,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Syntax { + let expected = Diagnostic::error(Error::Syntax { message: "doc comments cannot be applied to modules".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -196,10 +196,10 @@ mod comments { // Assert let expected = [ - Diagnostic::new(Error::Syntax { + Diagnostic::error(Error::Syntax { message: "doc comments cannot be applied to parameters".to_owned(), }), - Diagnostic::new(Error::Syntax { + Diagnostic::error(Error::Syntax { // TODO: improve the message for return members, since they're not parameters. // We need to find an umbrella term for return members and parameters. message: "doc comments cannot be applied to parameters".to_owned(), @@ -341,7 +341,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Lint::MalformedDocComment { + let expected = Diagnostic::lint(Lint::MalformedDocComment { message: "unknown doc comment tag 'linked'".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -361,7 +361,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Lint::BrokenDocLink { + let expected = Diagnostic::lint(Lint::BrokenDocLink { message: "no element named 'OtherStruct' exists in scope".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -389,7 +389,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Lint::BrokenDocLink { + let expected = Diagnostic::lint(Lint::BrokenDocLink { message: format!("{kind} cannot be linked to"), }); check_diagnostics(diagnostics, [expected]); @@ -411,7 +411,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Lint::IncorrectDocComment { + let expected = Diagnostic::lint(Lint::IncorrectDocComment { message: "comment has a 'param' tag for 'foo', but operation 'op' has no parameter with that name" .to_owned(), }); @@ -434,7 +434,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Lint::IncorrectDocComment { + let expected = Diagnostic::lint(Lint::IncorrectDocComment { message: "comment has a 'param' tag for 'foo', but operation 'op' has no parameter with that name" .to_owned(), }); @@ -460,7 +460,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Lint::IncorrectDocComment { + let expected = Diagnostic::lint(Lint::IncorrectDocComment { message: "comment has a 'returns' tag, but operation 'op' does not return anything".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -482,7 +482,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Lint::IncorrectDocComment { + let expected = Diagnostic::lint(Lint::IncorrectDocComment { message: "comment has a 'returns' tag for 'foo', but operation 'op' doesn't return anything with that name" .to_owned(), }); @@ -505,7 +505,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Lint::IncorrectDocComment { + let expected = Diagnostic::lint(Lint::IncorrectDocComment { message: "comment has a 'returns' tag for 'foo', but operation 'op' doesn't return anything with that name" .to_owned(), }); @@ -526,7 +526,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Lint::IncorrectDocComment { + let expected = Diagnostic::lint(Lint::IncorrectDocComment { message: "comment has a 'param' tag, but only operations can have parameters".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -546,7 +546,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Lint::IncorrectDocComment { + let expected = Diagnostic::lint(Lint::IncorrectDocComment { message: "comment has a 'returns' tag, but only operations can return".to_owned(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/cycle_tests.rs b/slicec/tests/cycle_tests.rs index a1eef988e..461bf058c 100644 --- a/slicec/tests/cycle_tests.rs +++ b/slicec/tests/cycle_tests.rs @@ -23,7 +23,7 @@ mod container { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::InfiniteSizeCycle { + let expected = Diagnostic::error(Error::InfiniteSizeCycle { type_id: "Test::Container".to_owned(), cycle: "Test::Container -> Test::Container".to_owned(), }); @@ -49,7 +49,7 @@ mod container { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::InfiniteSizeCycle { + let expected = Diagnostic::error(Error::InfiniteSizeCycle { type_id: "Test::Container".to_owned(), cycle: "Test::Container -> Test::Inner -> Test::Container".to_owned(), }); @@ -75,7 +75,7 @@ mod container { let diagnostics = parse_for_diagnostics(slice); // Assert: only `Container` should be marked as cyclic here. - let expected = Diagnostic::new(Error::InfiniteSizeCycle { + let expected = Diagnostic::error(Error::InfiniteSizeCycle { type_id: "Test::Container".to_owned(), cycle: "Test::Container -> Test::Container".to_owned(), }); @@ -99,7 +99,7 @@ mod container { let diagnostics = parse_for_diagnostics(slice); // Assert: only one error is emitted, despite multiple cyclic paths existing. - let expected = Diagnostic::new(Error::InfiniteSizeCycle { + let expected = Diagnostic::error(Error::InfiniteSizeCycle { type_id: "Test::Container".to_owned(), cycle: "Test::Container -> Test::Container".to_owned(), }); @@ -122,19 +122,19 @@ mod container { // Assert: There are technically 18 cycles in the above Slice, but only 4 are unique cycles. let expected = [ - Diagnostic::new(Error::InfiniteSizeCycle { + Diagnostic::error(Error::InfiniteSizeCycle { type_id: "Test::A".to_owned(), cycle: "Test::A -> Test::B -> Test::A".to_owned(), }), - Diagnostic::new(Error::InfiniteSizeCycle { + Diagnostic::error(Error::InfiniteSizeCycle { type_id: "Test::A".to_owned(), cycle: "Test::A -> Test::B -> Test::C -> Test::A".to_owned(), }), - Diagnostic::new(Error::InfiniteSizeCycle { + Diagnostic::error(Error::InfiniteSizeCycle { type_id: "Test::A".to_owned(), cycle: "Test::A -> Test::C -> Test::A".to_owned(), }), - Diagnostic::new(Error::InfiniteSizeCycle { + Diagnostic::error(Error::InfiniteSizeCycle { type_id: "Test::B".to_owned(), cycle: "Test::B -> Test::C -> Test::B".to_owned(), }), @@ -162,7 +162,7 @@ mod builtin { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::InfiniteSizeCycle { + let expected = Diagnostic::error(Error::InfiniteSizeCycle { type_id: "Test::Foo".to_owned(), cycle: "Test::Foo -> Test::Foo".to_owned(), }) @@ -189,7 +189,7 @@ mod builtin { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::InfiniteSizeCycle { + let expected = Diagnostic::error(Error::InfiniteSizeCycle { type_id: "Test::Foo".to_owned(), cycle: "Test::Foo -> Test::Foo".to_owned(), }) @@ -216,7 +216,7 @@ mod builtin { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::InfiniteSizeCycle { + let expected = Diagnostic::error(Error::InfiniteSizeCycle { type_id: "Test::Foo".to_owned(), cycle: "Test::Foo -> Test::Foo".to_owned(), }) @@ -245,12 +245,12 @@ mod type_aliases { // Assert let expected = [ - Diagnostic::new(Error::SelfReferentialTypeAliasNeedsConcreteType { + Diagnostic::error(Error::SelfReferentialTypeAliasNeedsConcreteType { identifier: "Test::Foo".to_owned(), }) .add_note("failed to resolve type due to a cycle in its definition", None) .add_note("cycle: Test::Foo -> Test::Foo".to_owned(), None), - Diagnostic::new(Error::DoesNotExist { + Diagnostic::error(Error::DoesNotExist { identifier: "Test::Foo".to_owned(), }), ]; @@ -273,20 +273,20 @@ mod type_aliases { // Assert let expected = [ - Diagnostic::new(Error::SelfReferentialTypeAliasNeedsConcreteType { + Diagnostic::error(Error::SelfReferentialTypeAliasNeedsConcreteType { identifier: "Test::Bar".to_owned(), }) .add_note("failed to resolve type due to a cycle in its definition", None) .add_note("cycle: Test::Bar -> Test::Foo -> Test::Bar".to_owned(), None), - Diagnostic::new(Error::DoesNotExist { + Diagnostic::error(Error::DoesNotExist { identifier: "Test::Bar".to_owned(), }), - Diagnostic::new(Error::SelfReferentialTypeAliasNeedsConcreteType { + Diagnostic::error(Error::SelfReferentialTypeAliasNeedsConcreteType { identifier: "Test::Foo".to_owned(), }) .add_note("failed to resolve type due to a cycle in its definition", None) .add_note("cycle: Test::Foo -> Test::Bar -> Test::Foo".to_owned(), None), - Diagnostic::new(Error::DoesNotExist { + Diagnostic::error(Error::DoesNotExist { identifier: "Test::Foo".to_owned(), }), ]; @@ -308,20 +308,20 @@ mod type_aliases { // Assert: only `Foo` should be marked as cyclic here. let expected = [ - Diagnostic::new(Error::SelfReferentialTypeAliasNeedsConcreteType { + Diagnostic::error(Error::SelfReferentialTypeAliasNeedsConcreteType { identifier: "Test::Foo".to_owned(), }) .add_note("failed to resolve type due to a cycle in its definition", None) .add_note("cycle: Test::Foo -> Test::Foo".to_owned(), None), - Diagnostic::new(Error::DoesNotExist { + Diagnostic::error(Error::DoesNotExist { identifier: "Test::Foo".to_owned(), }), - Diagnostic::new(Error::SelfReferentialTypeAliasNeedsConcreteType { + Diagnostic::error(Error::SelfReferentialTypeAliasNeedsConcreteType { identifier: "Test::Foo".to_owned(), }) .add_note("failed to resolve type due to a cycle in its definition", None) .add_note("cycle: Test::Foo -> Test::Foo".to_owned(), None), - Diagnostic::new(Error::DoesNotExist { + Diagnostic::error(Error::DoesNotExist { identifier: "Test::Foo".to_owned(), }), ]; diff --git a/slicec/tests/dictionaries/key_type.rs b/slicec/tests/dictionaries/key_type.rs index 457b08991..b216941f3 100644 --- a/slicec/tests/dictionaries/key_type.rs +++ b/slicec/tests/dictionaries/key_type.rs @@ -16,7 +16,7 @@ fn optional_keys_are_disallowed() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::KeyMustBeNonOptional); + let expected = Diagnostic::error(Error::KeyMustBeNonOptional); check_diagnostics(diagnostics, [expected]); } @@ -62,7 +62,7 @@ fn disallowed_primitive_types(key_type: &str) { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::KeyTypeNotSupported { kind: key_type.to_owned() }); + let expected = Diagnostic::error(Error::KeyTypeNotSupported { kind: key_type.to_owned() }); check_diagnostics(diagnostics, [expected]); } @@ -81,7 +81,7 @@ fn collections_are_disallowed(key_type: &str, key_kind: &str) { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::KeyTypeNotSupported { kind: key_kind.to_owned() }); + let expected = Diagnostic::error(Error::KeyTypeNotSupported { kind: key_kind.to_owned() }); check_diagnostics(diagnostics, [expected]); } @@ -119,7 +119,7 @@ fn disallowed_constructed_types(key_type: &str, key_type_def: &str, key_kind: &s let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::KeyTypeNotSupported { + let expected = Diagnostic::error(Error::KeyTypeNotSupported { kind: format!("{key_kind} '{key_type}'"), }); check_diagnostics(diagnostics, [expected]); @@ -140,7 +140,7 @@ fn non_compact_structs_are_disallowed() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::StructKeyMustBeCompact); + let expected = Diagnostic::error(Error::StructKeyMustBeCompact); check_diagnostics(diagnostics, [expected]); } @@ -190,7 +190,7 @@ fn compact_struct_with_disallowed_fields_is_disallowed() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::StructKeyContainsDisallowedType { + let expected = Diagnostic::error(Error::StructKeyContainsDisallowedType { struct_identifier: "Outer".to_owned(), }) .add_note("invalid dictionary key type: sequence", None) diff --git a/slicec/tests/dictionaries/value_type.rs b/slicec/tests/dictionaries/value_type.rs index 075540552..2a42b60f3 100644 --- a/slicec/tests/dictionaries/value_type.rs +++ b/slicec/tests/dictionaries/value_type.rs @@ -19,10 +19,10 @@ fn invalid_dictionary_values_produce_error() { // Assert let expected = [ - Diagnostic::new(Error::KeyTypeNotSupported { + Diagnostic::error(Error::KeyTypeNotSupported { kind: "float32".to_owned(), }), - Diagnostic::new(Error::KeyTypeNotSupported { + Diagnostic::error(Error::KeyTypeNotSupported { kind: "float64".to_owned(), }), ]; diff --git a/slicec/tests/enums/container.rs b/slicec/tests/enums/container.rs index 2b239c815..c97550451 100644 --- a/slicec/tests/enums/container.rs +++ b/slicec/tests/enums/container.rs @@ -22,7 +22,7 @@ fn enumerator_invalid_identifiers(identifier: &str, expected_message: &str) { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Syntax { + let expected = Diagnostic::error(Error::Syntax { message: expected_message.to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -64,7 +64,7 @@ mod associated_fields { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::CompactTypeCannotContainTaggedFields { kind: "enum" }) + let expected = Diagnostic::error(Error::CompactTypeCannotContainTaggedFields { kind: "enum" }) .add_note("enum 'E' is declared compact here", None); check_diagnostics(diagnostics, [expected]); @@ -125,25 +125,25 @@ mod associated_fields { // Arrange let expected = [ - Diagnostic::new(Error::EnumeratorValueOutOfBounds { + Diagnostic::error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "ExplicitNegative".to_owned(), value: -3, min: 0, max: i32::MAX as i128, }), - Diagnostic::new(Error::EnumeratorValueOutOfBounds { + Diagnostic::error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "ImplicitNegative".to_owned(), value: -2, min: 0, max: i32::MAX as i128, }), - Diagnostic::new(Error::EnumeratorValueOutOfBounds { + Diagnostic::error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "ImplicitOverflow".to_owned(), value: 2_147_483_648, min: 0, max: i32::MAX as i128, }), - Diagnostic::new(Error::EnumeratorValueOutOfBounds { + Diagnostic::error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "ExplicitOverflow".to_owned(), value: 0x686921203A7629, min: 0, @@ -241,7 +241,7 @@ mod associated_fields { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::MustContainEnumerators { + let expected = Diagnostic::error(Error::MustContainEnumerators { enum_identifier: "E".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -277,7 +277,7 @@ mod associated_fields { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Redefinition { + let expected = Diagnostic::error(Error::Redefinition { identifier: "A".to_string(), }) .add_note("'A' was previously defined here", None); @@ -306,7 +306,7 @@ mod underlying_type { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::EnumeratorCannotContainFields { + let expected = Diagnostic::error(Error::EnumeratorCannotContainFields { enumerator_identifier: "B".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -372,13 +372,13 @@ mod underlying_type { // Assert let expected = [ - Diagnostic::new(Error::EnumeratorValueOutOfBounds { + Diagnostic::error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "B".to_owned(), value: i128::MAX, min: -2147483648, max: 2147483647, }), - Diagnostic::new(Error::EnumeratorValueOutOfBounds { + Diagnostic::error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "C".to_owned(), value: i128::MIN, min: -2147483648, @@ -420,7 +420,7 @@ mod underlying_type { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::EnumeratorValueOutOfBounds { + let expected = Diagnostic::error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "A".to_owned(), value: out_of_bounds_value, min: -32768_i128, @@ -464,7 +464,7 @@ mod underlying_type { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::DuplicateEnumeratorValue { enumerator_value: 1 }) + let expected = Diagnostic::error(Error::DuplicateEnumeratorValue { enumerator_value: 1 }) .add_note("the value was previously used by 'A' here:", None); check_diagnostics(diagnostics, [expected]); @@ -505,7 +505,7 @@ mod underlying_type { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::MustContainEnumerators { + let expected = Diagnostic::error(Error::MustContainEnumerators { enum_identifier: "E".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -568,7 +568,7 @@ mod underlying_type { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::DuplicateEnumeratorValue { enumerator_value: 79 }); + let expected = Diagnostic::error(Error::DuplicateEnumeratorValue { enumerator_value: 79 }); check_diagnostics(diagnostics, [expected]); } @@ -587,7 +587,7 @@ mod underlying_type { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Redefinition { + let expected = Diagnostic::error(Error::Redefinition { identifier: "A".to_string(), }) .add_note("'A' was previously defined here", None); diff --git a/slicec/tests/enums/mod.rs b/slicec/tests/enums/mod.rs index e94e86c81..123ae0b84 100644 --- a/slicec/tests/enums/mod.rs +++ b/slicec/tests/enums/mod.rs @@ -51,7 +51,7 @@ fn invalid_underlying_type(underlying_type: &str) { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::EnumUnderlyingTypeNotSupported { + let expected = Diagnostic::error(Error::EnumUnderlyingTypeNotSupported { enum_identifier: "E".to_owned(), kind: Some(underlying_type.to_owned()), }); @@ -73,7 +73,7 @@ fn optional_underlying_types_fail() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::CannotUseOptionalUnderlyingType { + let expected = Diagnostic::error(Error::CannotUseOptionalUnderlyingType { enum_identifier: "E".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -118,7 +118,7 @@ fn compact_enums_cannot_have_underlying_types() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::CannotBeCompact { + let expected = Diagnostic::error(Error::CannotBeCompact { kind: "enum", identifier: "E".to_owned(), }) @@ -143,7 +143,7 @@ fn compact_enums_cannot_be_unchecked() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::CannotBeCompact { + let expected = Diagnostic::error(Error::CannotBeCompact { kind: "enum", identifier: "E".to_owned(), }) diff --git a/slicec/tests/files/io.rs b/slicec/tests/files/io.rs index de1cc93fc..4704dce2f 100644 --- a/slicec/tests/files/io.rs +++ b/slicec/tests/files/io.rs @@ -45,7 +45,7 @@ fn duplicate_source_files_ignored_with_warning() { // Assert assert_eq!(files.len(), 1); - let expected = Diagnostic::new(Lint::DuplicateFile { + let expected = Diagnostic::lint(Lint::DuplicateFile { path: "tests/files/../files/test.slice".to_owned(), }); check_diagnostics(diagnostics.into_inner(), [expected]); @@ -71,7 +71,7 @@ fn duplicate_reference_files_ignored_with_warning() { // Assert assert_eq!(files.len(), 1); - let expected = Diagnostic::new(Lint::DuplicateFile { + let expected = Diagnostic::lint(Lint::DuplicateFile { path: "tests/files/../files/test.slice".to_owned(), }); check_diagnostics(diagnostics.into_inner(), [expected]); diff --git a/slicec/tests/identifier_tests.rs b/slicec/tests/identifier_tests.rs index f96d831a9..5285c51c4 100644 --- a/slicec/tests/identifier_tests.rs +++ b/slicec/tests/identifier_tests.rs @@ -53,7 +53,7 @@ fn must_start_with_a_letter() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Syntax { + let expected = Diagnostic::error(Error::Syntax { message: "unknown symbol '_'".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -88,7 +88,7 @@ fn must_be_ascii_alphanumeric_characters() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Syntax { + let expected = Diagnostic::error(Error::Syntax { message: "unknown symbol 'ð’…‹'".to_owned(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/interfaces/inheritance.rs b/slicec/tests/interfaces/inheritance.rs index 7a89eb79e..94f62ef6b 100644 --- a/slicec/tests/interfaces/inheritance.rs +++ b/slicec/tests/interfaces/inheritance.rs @@ -81,7 +81,7 @@ fn must_inherit_from_interface() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::TypeMismatch { + let expected = Diagnostic::error(Error::TypeMismatch { expected: "interface".to_owned(), actual: "struct".to_owned(), is_concrete: true, @@ -108,7 +108,7 @@ fn operation_shadowing_is_disallowed() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Shadows { + let expected = Diagnostic::error(Error::Shadows { identifier: "op".to_owned(), }) .add_note("'op' was previously defined here", None); diff --git a/slicec/tests/interfaces/mod.rs b/slicec/tests/interfaces/mod.rs index b92ecbf64..b3a973a65 100644 --- a/slicec/tests/interfaces/mod.rs +++ b/slicec/tests/interfaces/mod.rs @@ -81,7 +81,7 @@ fn cannot_redefine_operations() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Redefinition { + let expected = Diagnostic::error(Error::Redefinition { identifier: "op".to_owned(), }) .add_note("'op' was previously defined here", None); diff --git a/slicec/tests/interfaces/operations.rs b/slicec/tests/interfaces/operations.rs index 87efddd10..847262ef3 100644 --- a/slicec/tests/interfaces/operations.rs +++ b/slicec/tests/interfaces/operations.rs @@ -190,7 +190,7 @@ fn cannot_redefine_parameters() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Redefinition { + let expected = Diagnostic::error(Error::Redefinition { identifier: "a".to_string(), }) .add_note("'a' was previously defined here", None); @@ -213,7 +213,7 @@ fn cannot_redefine_return_members() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Redefinition { + let expected = Diagnostic::error(Error::Redefinition { identifier: "a".to_string(), }) .add_note("'a' was previously defined here", None); @@ -239,7 +239,7 @@ fn return_tuple_must_contain_two_or_more_elements(return_tuple: &str) { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::ReturnTuplesMustContainAtLeastTwoElements); + let expected = Diagnostic::error(Error::ReturnTuplesMustContainAtLeastTwoElements); check_diagnostics(diagnostics, [expected]); } @@ -287,10 +287,10 @@ mod streams { // Assert let expected = [ - Diagnostic::new(Error::StreamedMembersMustBeLast { + Diagnostic::error(Error::StreamedMembersMustBeLast { parameter_identifier: "s".to_owned(), }), - Diagnostic::new(Error::MultipleStreamedMembers), + Diagnostic::error(Error::MultipleStreamedMembers), ]; check_diagnostics(diagnostics, expected); } @@ -310,7 +310,7 @@ mod streams { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::StreamedMembersMustBeLast { + let expected = Diagnostic::error(Error::StreamedMembersMustBeLast { parameter_identifier: "s".to_owned(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/module_tests.rs b/slicec/tests/module_tests.rs index 0328cb90f..019acdca2 100644 --- a/slicec/tests/module_tests.rs +++ b/slicec/tests/module_tests.rs @@ -46,7 +46,7 @@ mod module { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Syntax { + let expected = Diagnostic::error(Error::Syntax { message: "module declaration is required".to_owned(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/parser_tests.rs b/slicec/tests/parser_tests.rs index 3d682ee1c..6a81bdf6e 100644 --- a/slicec/tests/parser_tests.rs +++ b/slicec/tests/parser_tests.rs @@ -49,7 +49,7 @@ fn string_literals_cannot_contain_newlines() { // Assert let span = Span::new((2, 14).into(), (2, 24).into(), "string-0"); - let expected = Diagnostic::new(Error::Syntax { + let expected = Diagnostic::error(Error::Syntax { message: "unterminated string literal".to_owned(), }) .set_span(&span); @@ -112,10 +112,10 @@ fn files_are_parsed_independently() { // Assert let expected_message = "expected one of 'doc comment', 'struct', 'interface', 'enum', 'custom', 'typealias', 'compact', 'unchecked', '[', or '::', but found '-'"; let expected = [ - Diagnostic::new(Error::Syntax { + Diagnostic::error(Error::Syntax { message: expected_message.to_owned(), }), - Diagnostic::new(Error::Syntax { + Diagnostic::error(Error::Syntax { message: expected_message.to_owned(), }), ]; diff --git a/slicec/tests/preprocessor_tests.rs b/slicec/tests/preprocessor_tests.rs index 22f7784ca..271a924ce 100644 --- a/slicec/tests/preprocessor_tests.rs +++ b/slicec/tests/preprocessor_tests.rs @@ -69,7 +69,7 @@ fn identifiers_must_start_with_a_letter(identifier: &str) { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Syntax { + let expected = Diagnostic::error(Error::Syntax { message: format!("unknown symbol '{}'", identifier.chars().next().unwrap()), }); check_diagnostics(diagnostics, [expected]); @@ -357,7 +357,7 @@ fn preprocessor_single_backslash_suggestion() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Syntax { + let expected = Diagnostic::error(Error::Syntax { message: "unknown symbol '/', try using '//' instead".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -381,10 +381,10 @@ fn preprocessor_recovers_at_end_of_line() { // Assert let expected = [ - Diagnostic::new(Error::Syntax { + Diagnostic::error(Error::Syntax { message: "expected directive_end, but found 'Identifier(\"Bar\")'".to_owned(), }), - Diagnostic::new(Error::Syntax { + Diagnostic::error(Error::Syntax { message: r#"expected one of "&&", "||", or ")", but found 'DirectiveEnd'"#.to_owned(), }), ]; diff --git a/slicec/tests/redefinition_tests.rs b/slicec/tests/redefinition_tests.rs index e6e7e3ac0..f2079652c 100644 --- a/slicec/tests/redefinition_tests.rs +++ b/slicec/tests/redefinition_tests.rs @@ -26,7 +26,7 @@ mod redefinition { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Redefinition { + let expected = Diagnostic::error(Error::Redefinition { identifier: "S".to_owned(), }) .set_span(&Span::new((8, 20).into(), (8, 21).into(), "string-0")) @@ -55,7 +55,7 @@ mod redefinition { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Redefinition { + let expected = Diagnostic::error(Error::Redefinition { identifier: "A".to_owned(), }) .set_span(&Span::new((6, 20).into(), (6, 21).into(), "string-0")) @@ -87,7 +87,7 @@ mod redefinition { let diagnostics = parse_for_diagnostics(slice); // Assert - let i_error = Diagnostic::new(Error::Redefinition { + let i_error = Diagnostic::error(Error::Redefinition { identifier: "i".to_owned(), }) .set_span(&Span::new((6, 17).into(), (6, 18).into(), "string-0")) @@ -96,7 +96,7 @@ mod redefinition { Some(&Span::new((5, 17).into(), (5, 18).into(), "string-0")), ); - let s_error = Diagnostic::new(Error::Redefinition { + let s_error = Diagnostic::error(Error::Redefinition { identifier: "A".to_owned(), }) .set_span(&Span::new((9, 23).into(), (9, 24).into(), "string-0")) @@ -137,37 +137,37 @@ mod redefinition { // Assert let expected = [ // The struct fields - Diagnostic::new(Error::Redefinition { + Diagnostic::error(Error::Redefinition { identifier: "b".to_owned(), }) .set_span(&Span::new((8, 17).into(), (8, 18).into(), "string-0")), // The interface - Diagnostic::new(Error::Redefinition { + Diagnostic::error(Error::Redefinition { identifier: "A".to_owned(), }) .set_span(&Span::new((11, 23).into(), (11, 24).into(), "string-0")), // The operation - Diagnostic::new(Error::Redefinition { + Diagnostic::error(Error::Redefinition { identifier: "b".to_owned(), }) .set_span(&Span::new((15, 17).into(), (15, 18).into(), "string-0")), // The parameter - Diagnostic::new(Error::Redefinition { + Diagnostic::error(Error::Redefinition { identifier: "b".to_owned(), }) .set_span(&Span::new((12, 28).into(), (12, 29).into(), "string-0")), // The return member - Diagnostic::new(Error::Redefinition { + Diagnostic::error(Error::Redefinition { identifier: "b".to_owned(), }) .set_span(&Span::new((12, 50).into(), (12, 51).into(), "string-0")), // The enum - Diagnostic::new(Error::Redefinition { + Diagnostic::error(Error::Redefinition { identifier: "A".to_owned(), }) .set_span(&Span::new((18, 18).into(), (18, 19).into(), "string-0")), // The enumerator - Diagnostic::new(Error::Redefinition { + Diagnostic::error(Error::Redefinition { identifier: "b".to_owned(), }) .set_span(&Span::new((18, 28).into(), (18, 29).into(), "string-0")), @@ -192,7 +192,7 @@ mod redefinition { let diagnostics = parse_multiple_for_diagnostics(&[slice1, slice2]); // Assert - let expected = Diagnostic::new(Error::Redefinition { + let expected = Diagnostic::error(Error::Redefinition { identifier: "Bar".to_owned(), }) .set_span(&Span::new((3, 20).into(), (3, 23).into(), "string-1")) diff --git a/slicec/tests/scope_resolution_tests.rs b/slicec/tests/scope_resolution_tests.rs index 121c7bd66..57193fb8b 100644 --- a/slicec/tests/scope_resolution_tests.rs +++ b/slicec/tests/scope_resolution_tests.rs @@ -178,7 +178,7 @@ mod scope_resolution { let diagnostics = parse_multiple_for_diagnostics(&[slice1, slice2]); // Assert - let expected = Diagnostic::new(Error::TypeMismatch { + let expected = Diagnostic::error(Error::TypeMismatch { expected: "type".to_string(), actual: "module".to_string(), is_concrete: false, @@ -201,7 +201,7 @@ mod scope_resolution { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::DoesNotExist { + let expected = Diagnostic::error(Error::DoesNotExist { identifier: "Nested::C".to_string(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/sequence_tests.rs b/slicec/tests/sequence_tests.rs index 660728296..5e4afacc2 100644 --- a/slicec/tests/sequence_tests.rs +++ b/slicec/tests/sequence_tests.rs @@ -44,7 +44,7 @@ mod sequences { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::KeyTypeNotSupported { + let expected = Diagnostic::error(Error::KeyTypeNotSupported { kind: "float32".to_owned(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/structs/container.rs b/slicec/tests/structs/container.rs index a32ed3474..c82eb2c16 100644 --- a/slicec/tests/structs/container.rs +++ b/slicec/tests/structs/container.rs @@ -78,7 +78,7 @@ mod structs { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Redefinition { + let expected = Diagnostic::error(Error::Redefinition { identifier: "a".to_owned(), }) .add_note("'a' was previously defined here", None); @@ -106,7 +106,7 @@ mod compact_structs { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::CompactStructCannotBeEmpty); + let expected = Diagnostic::error(Error::CompactStructCannotBeEmpty); check_diagnostics(diagnostics, [expected]); } } diff --git a/slicec/tests/structs/tags.rs b/slicec/tests/structs/tags.rs index 808216fca..2c7dd6783 100644 --- a/slicec/tests/structs/tags.rs +++ b/slicec/tests/structs/tags.rs @@ -49,7 +49,7 @@ mod compact_structs { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::CompactTypeCannotContainTaggedFields { kind: "struct" }) + let expected = Diagnostic::error(Error::CompactTypeCannotContainTaggedFields { kind: "struct" }) .add_note("struct 'S' is declared compact here", None); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/tag_tests.rs b/slicec/tests/tag_tests.rs index dd8026c1d..67ab09455 100644 --- a/slicec/tests/tag_tests.rs +++ b/slicec/tests/tag_tests.rs @@ -25,7 +25,7 @@ mod tags { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::TaggedMemberMustBeOptional { + let expected = Diagnostic::error(Error::TaggedMemberMustBeOptional { identifier: "b".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -45,7 +45,7 @@ mod tags { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::TaggedMemberMustBeOptional { + let expected = Diagnostic::error(Error::TaggedMemberMustBeOptional { identifier: "myParam".to_string(), }); check_diagnostics(diagnostics, [expected]); @@ -100,7 +100,7 @@ mod tags { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::CannotHaveDuplicateTag { + let expected = Diagnostic::error(Error::CannotHaveDuplicateTag { identifier: "b".to_owned(), }) .add_note("The tag '1' is already being used by member 'a'", None); @@ -143,7 +143,7 @@ mod tags { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::TagValueOutOfBounds); + let expected = Diagnostic::error(Error::TagValueOutOfBounds); check_diagnostics(diagnostics, [expected]); } @@ -161,7 +161,7 @@ mod tags { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::TagValueOutOfBounds); + let expected = Diagnostic::error(Error::TagValueOutOfBounds); check_diagnostics(diagnostics, [expected]); } @@ -179,7 +179,7 @@ mod tags { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::Syntax { + let expected = Diagnostic::error(Error::Syntax { message: "expected one of 'integer literal' or '-', but found 'test string'".to_owned(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/typealias_tests.rs b/slicec/tests/typealias_tests.rs index 7b939bbee..f1c795b9a 100644 --- a/slicec/tests/typealias_tests.rs +++ b/slicec/tests/typealias_tests.rs @@ -123,7 +123,7 @@ mod typealias { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::new(Error::TypeAliasOfOptional) + let expected = Diagnostic::error(Error::TypeAliasOfOptional) .set_span(&Span::new((3, 13).into(), (3, 27).into(), "string-0")) .add_note( "try removing the trailing `?` modifier from its definition", From d58dbd6670494b0a650ef0510f7d2a938bc22df2 Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Tue, 14 Apr 2026 15:01:03 -0400 Subject: [PATCH 2/9] Moved the 'ALLOWABLE_LINT_IDENTIFIERS' to the 'allow' module. --- slicec/src/grammar/attributes/allow.rs | 16 +++++++++++++--- slicec/src/slice_options.rs | 4 ++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/slicec/src/grammar/attributes/allow.rs b/slicec/src/grammar/attributes/allow.rs index 05ef1cf5e..5e7bde8f6 100644 --- a/slicec/src/grammar/attributes/allow.rs +++ b/slicec/src/grammar/attributes/allow.rs @@ -2,6 +2,16 @@ use super::*; +/// All the valid arguments that can be supplied to the `allow` metadata, or the `--allow` command line option. +pub const ALLOWABLE_LINT_IDENTIFIERS: [&'static str; 6] = [ + "All", + "DuplicateFile", + "Deprecated", + "MalformedDocComment", + "IncorrectDocComment", + "BrokenDocLink", +]; + #[derive(Debug)] pub struct Allow { pub allowed_lints: Vec, @@ -14,7 +24,7 @@ impl Allow { check_argument_count_is_within(1..usize::MAX, args, Self::directive(), span, diagnostics); for arg in args { - let mut is_valid = Lint::ALLOWABLE_LINT_IDENTIFIERS.contains(&arg.as_str()); + let mut is_valid = ALLOWABLE_LINT_IDENTIFIERS.contains(&arg.as_str()); // The `DuplicateFile` lint can't be configured by attributes because it's a command-line specific lint. if arg == "DuplicateFile" { @@ -24,14 +34,14 @@ impl Allow { // Report an error if the argument wasn't valid. if !is_valid { // TODO we should emit a link to the lint page when we write it! - let mut error = Diagnostic::new(Error::InvalidAttributeArgument { + let mut error = Diagnostic::error(Error::InvalidAttributeArgument { directive: "allow".to_owned(), argument: arg.to_owned(), }) .set_span(span); // Check if the argument only differs in case from a valid one. - let suggestion = Lint::ALLOWABLE_LINT_IDENTIFIERS + let suggestion = ALLOWABLE_LINT_IDENTIFIERS .iter() .find(|identifier| identifier.eq_ignore_ascii_case(arg)); if let Some(identifier) = suggestion { diff --git a/slicec/src/slice_options.rs b/slicec/src/slice_options.rs index 14bfd75ab..2f580d661 100644 --- a/slicec/src/slice_options.rs +++ b/slicec/src/slice_options.rs @@ -1,6 +1,6 @@ // Copyright (c) ZeroC, Inc. -use crate::diagnostics::Lint; +use crate::grammar::attributes::ALLOWABLE_LINT_IDENTIFIERS; use clap::ArgAction::Append; use clap::{Parser, ValueEnum}; @@ -38,7 +38,7 @@ pub struct SliceOptions { /// Instruct the compiler to allow the specified lint. // TODO add a link to the lint reference in this doc comment! - #[arg(short = 'A', long = "allow", num_args = 1, action = Append, value_name = "LINT_NAME", value_parser = Lint::ALLOWABLE_LINT_IDENTIFIERS, hide_possible_values = true, ignore_case = true)] + #[arg(short = 'A', long = "allow", num_args = 1, action = Append, value_name = "LINT_NAME", value_parser = ALLOWABLE_LINT_IDENTIFIERS, hide_possible_values = true, ignore_case = true)] pub allowed_lints: Vec, /// Validate input files without generating code for them. From 19fcf085b67ed62f5a3761c73c07f2a0a8452ed4 Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Tue, 14 Apr 2026 15:21:14 -0400 Subject: [PATCH 3/9] Removed the 'implement_diagnostic_functions_for' macro. --- slicec/src/diagnostics/errors.rs | 439 +++++++++++++------------------ slicec/src/diagnostics/lints.rs | 61 +++-- slicec/src/diagnostics/mod.rs | 97 ++----- 3 files changed, 239 insertions(+), 358 deletions(-) diff --git a/slicec/src/diagnostics/errors.rs b/slicec/src/diagnostics/errors.rs index 38a15ccf2..5b2df57ef 100644 --- a/slicec/src/diagnostics/errors.rs +++ b/slicec/src/diagnostics/errors.rs @@ -1,6 +1,5 @@ // Copyright (c) ZeroC, Inc. -use super::implement_diagnostic_functions; use crate::utils::string_util::indefinite_article; use std::ops::Range; @@ -234,273 +233,187 @@ pub enum Error { TypeAliasOfOptional, } -implement_diagnostic_functions!( - Error, - ( - "E001", - IO, - format!("unable to {action} '{path}': {}", io_error_message(error)), - action, - path, - error - ), - ( - "E002", - Syntax, - format!("invalid syntax: {message}"), - message - ), - ( - "E003", - KeyMustBeNonOptional, - "optional types are not valid dictionary key types" - ), - ( - "E004", - StructKeyMustBeCompact, - "structs must be compact to be used as a dictionary key type" - ), - ( - "E005", - KeyTypeNotSupported, - format!("invalid dictionary key type: {kind}"), - kind - ), - ( - "E006", - StructKeyContainsDisallowedType, - format!("struct '{struct_identifier}' contains fields that are not a valid dictionary key types"), - struct_identifier - ), - ( - "E007", - CannotUseOptionalUnderlyingType, - format!("invalid enum '{enum_identifier}': enums cannot have optional underlying types"), - enum_identifier - ), - ( - "E008", - MustContainEnumerators, - format!("invalid enum '{enum_identifier}': enums must contain at least one enumerator"), - enum_identifier - ), - ( - "E009", - EnumUnderlyingTypeNotSupported, - { - if let Some(kind) = kind { - format!("invalid enum '{enum_identifier}': underlying type '{kind}' is not supported", ) - } else { - format!("invalid enum '{enum_identifier}': missing required underlying type") +impl Error { + /// Returns the error code corresponding to this particular [`Error`]. + pub fn error_code(&self) -> &'static str { + match self { + Self::IO { .. } => "E001", + Self::Syntax { .. } => "E002", + Self::KeyMustBeNonOptional => "E003", + Self::StructKeyMustBeCompact => "E004", + Self::KeyTypeNotSupported { .. } => "E005", + Self::StructKeyContainsDisallowedType { .. } => "E006", + Self::CannotUseOptionalUnderlyingType { .. } => "E007", + Self::MustContainEnumerators { .. } => "E008", + Self::EnumUnderlyingTypeNotSupported { .. } => "E009", + Self::Redefinition { .. } => "E010", + Self::Shadows { .. } => "E011", + Self::CannotHaveDuplicateTag { .. } => "E012", + Self::StreamedMembersMustBeLast { .. } => "E013", + Self::ReturnTuplesMustContainAtLeastTwoElements => "E014", + Self::CompactTypeCannotContainTaggedFields { .. } => "E015", + Self::TaggedMemberMustBeOptional { .. } => "E016", + Self::TypeMismatch { .. } => "E017", + Self::CompactStructCannotBeEmpty => "E018", + Self::SelfReferentialTypeAliasNeedsConcreteType { .. } => "E019", + Self::EnumeratorValueOutOfBounds { .. } => "E020", + Self::TagValueOutOfBounds => "E021", + Self::DuplicateEnumeratorValue { .. } => "E022", + Self::InvalidAttribute { .. } => "E023", + Self::UnknownAttribute { .. } => "E024", + Self::MissingRequiredAttribute { .. } => "E025", + Self::AttributeIsNotRepeatable { .. } => "E026", + Self::InvalidAttributeArgument { .. } => "E027", + Self::IncorrectAttributeArgumentCount { .. } => "E028", + Self::MultipleStreamedMembers => "E029", + Self::IntegerLiteralOverflows => "E030", + Self::InvalidIntegerLiteral { .. } => "E031", + Self::InfiniteSizeCycle { .. } => "E032", + Self::DoesNotExist { .. } => "E033", + Self::TypeAliasOfOptional => "E034", + Self::EnumeratorCannotContainFields { .. } => "E035", + Self::CannotBeCompact { .. } => "E036", + } + } + + /// Returns a message describing this [`Error`] in detail. + pub fn message(&self) -> String { + match self { + Self::IO { action, path, error } => { + let message = match error.kind() { + std::io::ErrorKind::NotFound => "No such file or directory".to_owned(), + _ => error.to_string(), + }; + format!("unable to {action} '{path}': {message}") } - }, - enum_identifier, - kind - ), - ( - "E010", - Redefinition, - format!("redefinition of '{identifier}'"), - identifier - ), - ( - "E011", - Shadows, - format!("'{identifier}' shadows another symbol"), - identifier - ), - ( - "E012", - CannotHaveDuplicateTag, - format!("invalid tag on member '{identifier}': tags must be unique"), - identifier - ), - ( - "E013", - StreamedMembersMustBeLast, - format!("invalid parameter '{parameter_identifier}': only the last parameter in an operation can use the stream modifier"), - parameter_identifier - ), - ( - "E014", - ReturnTuplesMustContainAtLeastTwoElements, - "return tuples must have at least 2 elements" - ), - ( - "E015", - CompactTypeCannotContainTaggedFields, - format!("tagged fields are not supported in compact {kind}s; consider removing the tag, or making the {kind} non-compact"), - kind - ), - ( - "E016", - TaggedMemberMustBeOptional, - format!("invalid tag on member '{identifier}': tagged members must be optional"), - identifier - ), - ( - "E017", - TypeMismatch, - format!( - "type mismatch: expected {} '{expected}' but found {} '{actual}'{}", - indefinite_article(expected), - indefinite_article(actual), - if *is_concrete { - "".to_owned() - } else { - format!(" (which isn't {} '{expected}')", indefinite_article(expected)) + + Self::Syntax { message } => format!("invalid syntax: {message}"), + + Self::KeyMustBeNonOptional => "optional types are not valid dictionary key types".to_owned(), + + Self::StructKeyMustBeCompact => "structs must be compact to be used as a dictionary key type".to_owned(), + + Self::KeyTypeNotSupported { kind } => format!("invalid dictionary key type: {kind}"), + + Self::StructKeyContainsDisallowedType { struct_identifier } + => format!("struct '{struct_identifier}' contains fields that are not a valid dictionary key types"), + + Self::CannotUseOptionalUnderlyingType { enum_identifier } + => format!("invalid enum '{enum_identifier}': enums cannot have optional underlying types"), + + Self::MustContainEnumerators { enum_identifier } + => format!("invalid enum '{enum_identifier}': enums must contain at least one enumerator"), + + Self::EnumUnderlyingTypeNotSupported { enum_identifier, kind } => { + if let Some(kind) = kind { + format!("invalid enum '{enum_identifier}': underlying type '{kind}' is not supported", ) + } else { + format!("invalid enum '{enum_identifier}': missing required underlying type") + } + } + + Self::Redefinition { identifier } => format!("redefinition of '{identifier}'"), + + Self::Shadows { identifier } => format!("'{identifier}' shadows another symbol"), + + Self::CannotHaveDuplicateTag { identifier } + => format!("invalid tag on member '{identifier}': tags must be unique"), + + Self::StreamedMembersMustBeLast { parameter_identifier } + => format!("invalid parameter '{parameter_identifier}': only the last parameter in an operation can use the stream modifier"), + + Self::ReturnTuplesMustContainAtLeastTwoElements => "return tuples must have at least 2 elements".to_owned(), + + Self::CompactTypeCannotContainTaggedFields { kind } + => format!("tagged fields are not supported in compact {kind}s; consider removing the tag, or making the {kind} non-compact"), + + Self::TaggedMemberMustBeOptional { identifier } + => format!("invalid tag on member '{identifier}': tagged members must be optional"), + + Self::TypeMismatch { expected, actual, is_concrete } => { + format!( + "type mismatch: expected {} '{expected}' but found {} '{actual}'{}", + indefinite_article(expected), + indefinite_article(actual), + if *is_concrete { + "".to_owned() + } else { + format!(" (which isn't {} '{expected}')", indefinite_article(expected)) + } + ) } - ), - expected, - actual, - is_concrete - ), - ( - "E018", - CompactStructCannotBeEmpty, - "compact structs must be non-empty" - ), - ( - "E019", - SelfReferentialTypeAliasNeedsConcreteType, - format!("self-referential type alias '{identifier}' has no concrete type"), - identifier - ), - ( - "E020", - EnumeratorValueOutOfBounds, - format!( - "invalid enumerator '{enumerator_identifier}': enumerator value '{value}' is out of bounds. The value must be between '{min}..{max}', inclusive", - ), - enumerator_identifier, value, min, max - ), - ( - "E021", - TagValueOutOfBounds, - "tag values must be within the range 0 <= value <= 2147483647" - ), - ( - "E022", - DuplicateEnumeratorValue, - format!("enumerator values must be unique; the value '{enumerator_value}' is already in use"), - enumerator_value - ), - ( - "E023", - InvalidAttribute, - format!("invalid attribute '{directive}'"), - directive - ), - ( - "E024", - UnknownAttribute, - format!("unknown attribute '{directive}'"), - directive - ), - ( - "E025", - MissingRequiredAttribute, - format!("missing required attribute '{expected_attribute}'"), - expected_attribute - ), - ( - "E026", - AttributeIsNotRepeatable, - format!("duplicate attribute '{directive}'"), - directive - ), - ( - "E027", - InvalidAttributeArgument, - format!("'{argument}' is not a valid argument to the '{directive}' attribute"), - argument, - directive - ), - ( - "E028", - IncorrectAttributeArgumentCount, - { - let args_provided = if *actual_count == 1 { - String::from("1 argument was provided") - } else { - format!("{actual_count} arguments were provided") - }; - if expected_count.len() == 1 { - // If the range is only 1 element long, then this attribute requires an exact number of arguments. - let expected = expected_count.start; - if expected == 0 { - format!("attribute '{directive}' does not take any arguments, but {args_provided}") + + Self::CompactStructCannotBeEmpty => "compact structs must be non-empty".to_owned(), + + Self::SelfReferentialTypeAliasNeedsConcreteType { identifier } + => format!("self-referential type alias '{identifier}' has no concrete type"), + + Self::EnumeratorValueOutOfBounds { enumerator_identifier, value, min, max } + => format!("invalid enumerator '{enumerator_identifier}': enumerator value '{value}' is out of bounds. The value must be between '{min}..{max}', inclusive"), + + Self::TagValueOutOfBounds => "tag values must be within the range 0 <= value <= 2147483647".to_owned(), + + Self::DuplicateEnumeratorValue { enumerator_value } + => format!("enumerator values must be unique; the value '{enumerator_value}' is already in use"), + + Self::InvalidAttribute { directive } => format!("invalid attribute '{directive}'"), + + Self::UnknownAttribute { directive } => format!("unknown attribute '{directive}'"), + + Self::MissingRequiredAttribute { expected_attribute } + => format!("missing required attribute '{expected_attribute}'"), + + Self::AttributeIsNotRepeatable { directive } => format!("duplicate attribute '{directive}'"), + + Self::InvalidAttributeArgument { directive, argument } + => format!("'{argument}' is not a valid argument to the '{directive}' attribute"), + + Self::IncorrectAttributeArgumentCount { directive, expected_count, actual_count } => { + let args_provided = if *actual_count == 1 { + String::from("1 argument was provided") } else { - let only = if expected > *actual_count { "only " } else { "" }; + format!("{actual_count} arguments were provided") + }; + if expected_count.len() == 1 { + // If the range is only 1 element long, then this attribute requires an exact number of arguments. + let expected = expected_count.start; + if expected == 0 { + format!("attribute '{directive}' does not take any arguments, but {args_provided}") + } else { + let only = if expected > *actual_count { "only " } else { "" }; + let args = if expected == 1 { "argument" } else { "arguments" }; + format!("attribute '{directive}' takes exactly {expected} {args}, but {only}{args_provided}") + } + } else if expected_count.end == usize::MAX { + // If the range has no upper bound, then this attribute only requires a minimum number of arguments. + let expected = expected_count.start; let args = if expected == 1 { "argument" } else { "arguments" }; - format!("attribute '{directive}' takes exactly {expected} {args}, but {only}{args_provided}") + format!("attribute '{directive}' requires at least {expected} {args}, but only {args_provided}") + } else { + // Otherwise, this attribute accepts a specific range of possible arguments. + let min = expected_count.start; + let max = expected_count.end - 1; + format!("attribute '{directive}' takes between {min} and {max} arguments (inclusive), but {args_provided}") } - } else if expected_count.end == usize::MAX { - // If the range has no upper bound, then this attribute has only a minimum number of required arguments. - let expected = expected_count.start; - let args = if expected == 1 { "argument" } else { "arguments" }; - format!("attribute '{directive}' requires at least {expected} {args}, but only {args_provided}") - } else { - // Otherwise, this attribute accepts a specific range of possible arguments. - let min = expected_count.start; - let max = expected_count.end - 1; - format!("attribute '{directive}' takes between {min} and {max} arguments (inclusive), but {args_provided}") } - }, - directive, - expected_count, - actual_count - ), - ( - "E029", - MultipleStreamedMembers, - "cannot have multiple streamed members" - ), - ( - "E030", - IntegerLiteralOverflows, - "integer literal is outside the parsable range of -2^127 <= i <= 2^127 - 1" - ), - ( - "E031", - InvalidIntegerLiteral, - format!("integer literal contains illegal characters for base-{base}"), - base - ), - ( - "E032", - InfiniteSizeCycle, - format!("type {type_id} illegally references itself: {cycle}"), - type_id, cycle - ), - ( - "E033", - DoesNotExist, - format!("no element with identifier '{identifier}' exists"), - identifier - ), - ( - "E034", - TypeAliasOfOptional, - "optional types cannot be aliased" - ), - ( - "E035", - EnumeratorCannotContainFields, - format!("invalid enumerator '{enumerator_identifier}': fields cannot be declared within enums that specify an underlying type"), - enumerator_identifier - ), - ( - "E036", - CannotBeCompact, - format!("'{kind}' '{identifier}' cannot be marked compact"), - kind, identifier - ) -); - -fn io_error_message(error: &std::io::Error) -> String { - match error.kind() { - std::io::ErrorKind::NotFound => "No such file or directory".to_owned(), - _ => error.to_string(), + + Self::MultipleStreamedMembers => "cannot have multiple streamed members".to_owned(), + + Self::IntegerLiteralOverflows + => "integer literal is outside the parsable range of -2^127 <= i <= 2^127 - 1".to_owned(), + + Self::InvalidIntegerLiteral { base } => format!("integer literal contains illegal characters for base-{base}"), + + Self::InfiniteSizeCycle { type_id, cycle } => format!("type {type_id} illegally references itself: {cycle}"), + + Self::DoesNotExist { identifier } => format!("no element with identifier '{identifier}' exists"), + + Self::TypeAliasOfOptional => "optional types cannot be aliased".to_owned(), + + Self::EnumeratorCannotContainFields { enumerator_identifier } + => format!("invalid enumerator '{enumerator_identifier}': fields cannot be declared within enums that specify an underlying type"), + + Self::CannotBeCompact { kind, identifier } => format!("'{kind}' '{identifier}' cannot be marked compact"), + } } } diff --git a/slicec/src/diagnostics/lints.rs b/slicec/src/diagnostics/lints.rs index c8ee1c967..61d2e8413 100644 --- a/slicec/src/diagnostics/lints.rs +++ b/slicec/src/diagnostics/lints.rs @@ -1,6 +1,6 @@ // Copyright (c) ZeroC, Inc. -use super::{implement_diagnostic_functions, DiagnosticLevel}; +use super::DiagnosticLevel; #[derive(Debug)] pub enum Lint { @@ -36,8 +36,9 @@ pub enum Lint { } impl Lint { - /// Returns the default diagnostic level this lint should use when reporting violations. - pub fn get_default_level(&self) -> DiagnosticLevel { + /// Returns the default [`DiagnosticLevel`] this lint violation should be reported with unless affected by + /// attributes (like '[allow(...)]'), or command-line options (like '--allow'). + pub fn default_diagnostic_level(&self) -> DiagnosticLevel { match self { Self::DuplicateFile { .. } => DiagnosticLevel::Warning, Self::Deprecated { .. } => DiagnosticLevel::Warning, @@ -46,26 +47,36 @@ impl Lint { Self::IncorrectDocComment { .. } => DiagnosticLevel::Warning, } } -} -implement_diagnostic_functions!( - Lint, - ( - DuplicateFile, - format!("slice file was provided more than once: '{path}'"), - path - ), - ( - Deprecated, - if let Some(reason) = reason { - format!("'{identifier}' is deprecated: {reason}") - } else { - format!("'{identifier}' is deprecated") - }, - identifier, - reason - ), - (MalformedDocComment, message, message), - (IncorrectDocComment, message, message), - (BrokenDocLink, message, message) -); + /// Returns the name of the lint which was violated. + pub fn lint_name(&self) -> &'static str { + match self { + Self::DuplicateFile { .. } => "DuplicateFile", + Self::Deprecated { .. } => "Deprecated", + Self::MalformedDocComment { .. } => "MalformedDocComment", + Self::IncorrectDocComment { .. } => "IncorrectDocComment", + Self::BrokenDocLink { .. } => "BrokenDocLink", + } + } + + /// Returns a message describing this lint violation in detail. + pub fn message(&self) -> String { + match self { + Self::DuplicateFile { path } => format!("slice file was provided more than once: '{path}'"), + + Self::Deprecated { identifier, reason } => { + if let Some(reason) = reason { + format!("'{identifier}' is deprecated: {reason}") + } else { + format!("'{identifier}' is deprecated") + } + } + + Self::MalformedDocComment { message } => format!("malformed doc comment: {message}"), + + Self::IncorrectDocComment { message } => format!("incorrect doc comment: {message}"), + + Self::BrokenDocLink { message } => format!("broken doc link: {message}"), + } + } +} diff --git a/slicec/src/diagnostics/mod.rs b/slicec/src/diagnostics/mod.rs index 824693aea..ed6d8516a 100644 --- a/slicec/src/diagnostics/mod.rs +++ b/slicec/src/diagnostics/mod.rs @@ -1,86 +1,43 @@ // Copyright (c) ZeroC, Inc. -use crate::slice_file::Span; -use serde::Serialize; - mod diagnostic; mod errors; mod lints; -pub use diagnostic::*; +pub use diagnostic::{Diagnostic, Diagnostics}; pub use errors::Error; pub use lints::Lint; -/// Stores additional information about a diagnostic. -#[derive(Serialize, Debug, Clone)] -pub struct Note { - pub message: String, - pub span: Option, -} - -/// A macro that implements the `code` and `message` functions for [Lint] and [Error] enums. -macro_rules! implement_diagnostic_functions { - (Lint, $(($kind:ident, $message:expr $(, $variant:ident)* )),*) => { - impl Lint { - // TODO maybe we should move this somewhere other than `Lint`? Like in `Attribute` maybe? - /// This array contains all the valid arguments for the 'allow' attribute. - pub const ALLOWABLE_LINT_IDENTIFIERS: [&'static str; 6] = [ - "All", - $(stringify!($kind)),* - ]; - - pub fn code(&self) -> &str { - match self { - $( - implement_diagnostic_functions!(@error Lint::$kind, $($variant),*) => stringify!($kind), - )* - } - } - - pub fn message(&self) -> String { - match self { - $( - implement_diagnostic_functions!(@description Lint::$kind, $($variant),*) => $message.into(), - )* - } - } - } - }; +use crate::slice_file::Span; +use serde::Serialize; - (Error, $(($code:literal, $kind:ident, $message:expr $(, $variant:ident)* )),*) => { - impl Error { - pub fn code(&self) -> &str { - match self { - $( - implement_diagnostic_functions!(@error Error::$kind, $($variant),*) => $code, - )* - } - } +/// Wrapper enum for the 3 possible kinds of diagnostics. +#[derive(Debug)] +pub enum DiagnosticKind { + /// An irrecoverable error; the compiler will terminate early at the end of the next phase. + Error(Error), - pub fn message(&self) -> String { - match self { - $( - implement_diagnostic_functions!(@description Error::$kind, $($variant),*) => $message.into(), - )* - } - } - } - }; + /// A minor and recoverable mistake; has no effect on the compiler's execution pipe-line. + Lint(Lint), +} - (@error $kind:path,) => { - $kind - }; +/// Diagnostic levels describe the severity of a diagnostic, and how the compiler should react to their emission. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub enum DiagnosticLevel { + #[rustfmt::skip] // See https://github.com/rust-lang/rustfmt/issues/5801 + /// Diagnostics with the `Error` level will be emitted and will cause compilation to fail with a non-zero exit code. + Error, - (@error $kind:path, $($variant:ident),+) => { - $kind {..} - }; + /// Diagnostics with the `Warning` level will be emitted, but will not influence the exit code of the compiler. + Warning, - (@description $kind:path,) => { - $kind - }; + /// Diagnostics with the `Suppressed` level are ignored by the compiler and will not emit any message. + Suppressed, +} - (@description $kind:path, $($variant:ident),+) => { - $kind{$($variant),*} - }; +/// Stores additional information about a diagnostic. +#[derive(Serialize, Debug, Clone)] +pub struct Note { + pub message: String, + pub span: Option, } -pub(crate) use implement_diagnostic_functions; From ad517051c5a08ee3472e7775b8a9b9e5756884ee Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Tue, 14 Apr 2026 15:52:50 -0400 Subject: [PATCH 4/9] Keep the old 'Allowed' name for now. --- slicec/src/diagnostics/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slicec/src/diagnostics/mod.rs b/slicec/src/diagnostics/mod.rs index ed6d8516a..f20b0b826 100644 --- a/slicec/src/diagnostics/mod.rs +++ b/slicec/src/diagnostics/mod.rs @@ -31,8 +31,8 @@ pub enum DiagnosticLevel { /// Diagnostics with the `Warning` level will be emitted, but will not influence the exit code of the compiler. Warning, - /// Diagnostics with the `Suppressed` level are ignored by the compiler and will not emit any message. - Suppressed, + /// Diagnostics with the `Allowed` level are ignored by the compiler and will not emit any message. + Allowed, } /// Stores additional information about a diagnostic. From 1f5e93de8dc95d62e726a8ab55b76d6820b62aa9 Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Wed, 15 Apr 2026 10:46:30 -0400 Subject: [PATCH 5/9] Splitting this off into it's own PR for reviewability. --- slicec/src/diagnostics/diagnostic.rs | 25 +++++++++++++++++------ slicec/src/diagnostics/mod.rs | 26 +----------------------- slicec/src/grammar/attributes/allow.rs | 2 +- slicec/src/main.rs | 4 ++-- slicec/src/parsers/mod.rs | 2 +- slicec/src/validators/cycle_detection.rs | 8 ++++---- slicec/src/validators/dictionary.rs | 2 +- 7 files changed, 29 insertions(+), 40 deletions(-) diff --git a/slicec/src/diagnostics/diagnostic.rs b/slicec/src/diagnostics/diagnostic.rs index 18b76d0f9..97ea1bbd0 100644 --- a/slicec/src/diagnostics/diagnostic.rs +++ b/slicec/src/diagnostics/diagnostic.rs @@ -18,11 +18,12 @@ pub struct Diagnostic { } impl Diagnostic { - pub fn new(kind: impl Into) -> Self { - let kind = kind.into(); + /// Creates a new `Diagnostic` directly from a [`DiagnosticKind`]. + /// The newly created `Diagnostic` has no `span`, `scope`, or `notes` set. + pub fn new(kind: DiagnosticKind) -> Self { let level = match &kind { DiagnosticKind::Error(_) => DiagnosticLevel::Error, - DiagnosticKind::Lint(lint) => lint.get_default_level(), + DiagnosticKind::Lint(lint) => lint.default_diagnostic_level(), }; Diagnostic { @@ -34,6 +35,18 @@ impl Diagnostic { } } + /// Creates a new error `Diagnostic` from the provided [`Error`]. + /// The newly created `Diagnostic` has no `span`, `scope`, or `notes` set. + pub fn error(error: Error) -> Self { + Self::new(DiagnosticKind::Error(error)) + } + + /// Creates a new lint `Diagnostic` from the provided [`Lint`]. + /// The newly created `Diagnostic` has no `span`, `scope`, or `notes` set. + pub fn lint(lint: Lint) -> Self { + Self::new(DiagnosticKind::Lint(lint)) + } + /// Returns the message of this diagnostic. pub fn message(&self) -> String { match &self.kind { @@ -45,8 +58,8 @@ impl Diagnostic { /// Returns this diagnostic's code. This is either the name of a lint or of the form `E###`. pub fn code(&self) -> &str { match &self.kind { - DiagnosticKind::Error(error) => error.code(), - DiagnosticKind::Lint(lint) => lint.code(), + DiagnosticKind::Error(error) => error.error_code(), + DiagnosticKind::Lint(lint) => lint.lint_name(), } } @@ -160,7 +173,7 @@ impl Diagnostics { pub fn into_updated(mut self, ast: &Ast, files: &[SliceFile], options: &SliceOptions) -> Vec { // Helper function that checks whether a lint should be allowed according to the provided identifiers. fn is_lint_allowed_by<'b>(mut identifiers: impl Iterator, lint: &Lint) -> bool { - identifiers.any(|identifier| identifier == "All" || identifier == lint.code()) + identifiers.any(|identifier| identifier == "All" || identifier == lint.lint_name()) } // Helper function that checks whether a lint is allowed by attributes on the provided entity. diff --git a/slicec/src/diagnostics/mod.rs b/slicec/src/diagnostics/mod.rs index f20b0b826..61690c404 100644 --- a/slicec/src/diagnostics/mod.rs +++ b/slicec/src/diagnostics/mod.rs @@ -4,37 +4,13 @@ mod diagnostic; mod errors; mod lints; -pub use diagnostic::{Diagnostic, Diagnostics}; +pub use diagnostic::*; pub use errors::Error; pub use lints::Lint; use crate::slice_file::Span; use serde::Serialize; -/// Wrapper enum for the 3 possible kinds of diagnostics. -#[derive(Debug)] -pub enum DiagnosticKind { - /// An irrecoverable error; the compiler will terminate early at the end of the next phase. - Error(Error), - - /// A minor and recoverable mistake; has no effect on the compiler's execution pipe-line. - Lint(Lint), -} - -/// Diagnostic levels describe the severity of a diagnostic, and how the compiler should react to their emission. -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub enum DiagnosticLevel { - #[rustfmt::skip] // See https://github.com/rust-lang/rustfmt/issues/5801 - /// Diagnostics with the `Error` level will be emitted and will cause compilation to fail with a non-zero exit code. - Error, - - /// Diagnostics with the `Warning` level will be emitted, but will not influence the exit code of the compiler. - Warning, - - /// Diagnostics with the `Allowed` level are ignored by the compiler and will not emit any message. - Allowed, -} - /// Stores additional information about a diagnostic. #[derive(Serialize, Debug, Clone)] pub struct Note { diff --git a/slicec/src/grammar/attributes/allow.rs b/slicec/src/grammar/attributes/allow.rs index 5e7bde8f6..da6103e5f 100644 --- a/slicec/src/grammar/attributes/allow.rs +++ b/slicec/src/grammar/attributes/allow.rs @@ -3,7 +3,7 @@ use super::*; /// All the valid arguments that can be supplied to the `allow` metadata, or the `--allow` command line option. -pub const ALLOWABLE_LINT_IDENTIFIERS: [&'static str; 6] = [ +pub const ALLOWABLE_LINT_IDENTIFIERS: [&str; 6] = [ "All", "DuplicateFile", "Deprecated", diff --git a/slicec/src/main.rs b/slicec/src/main.rs index d65d075e2..28fe69506 100644 --- a/slicec/src/main.rs +++ b/slicec/src/main.rs @@ -130,7 +130,7 @@ fn handle_generator_response(response_payload: Vec, output_dir: &Option) { parse_file(file, &mut state.ast, &mut diagnostics, symbols.clone()); // Store any diagnostics that were emitted during parsing. - state.diagnostics.extend(diagnostics.into_inner()); + state.diagnostics.extend(diagnostics); } } diff --git a/slicec/src/validators/cycle_detection.rs b/slicec/src/validators/cycle_detection.rs index bec6112c3..fc271bc03 100644 --- a/slicec/src/validators/cycle_detection.rs +++ b/slicec/src/validators/cycle_detection.rs @@ -147,10 +147,10 @@ impl<'a> CycleDetector<'a> { let cycle_notes = self.dependency_stack.iter().map(|(_, field)| Self::get_note_for(field)); // Report the error. - let mut error = Diagnostic::error(Error::InfiniteSizeCycle { type_id, cycle }); - error = error.set_span(type_being_checked.1.span()); - error.notes = cycle_notes.collect(); - self.diagnostics.push(error); + Diagnostic::error(Error::InfiniteSizeCycle { type_id, cycle }) + .set_span(type_being_checked.1.span()) + .extend_notes(cycle_notes) + .push_into(self.diagnostics); } fn get_note_for(field: &Field) -> Note { diff --git a/slicec/src/validators/dictionary.rs b/slicec/src/validators/dictionary.rs index cc204d9c3..ce0c49951 100644 --- a/slicec/src/validators/dictionary.rs +++ b/slicec/src/validators/dictionary.rs @@ -42,7 +42,7 @@ fn check_dictionary_key_type(type_ref: &TypeRef) -> Option { // Convert each error into a note and add it to the struct key error. for e in errors { - error = error.add_note(e.message(), e.span.as_ref()); + error = error.add_note(e.message(), e.span()); } return Some(error); } From 3972569d2d690c28ecd158fe9bea880794d8edd7 Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Wed, 15 Apr 2026 10:57:36 -0400 Subject: [PATCH 6/9] Remove 'From' impls. --- slicec/src/diagnostics/diagnostic.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/slicec/src/diagnostics/diagnostic.rs b/slicec/src/diagnostics/diagnostic.rs index 97ea1bbd0..001f6e820 100644 --- a/slicec/src/diagnostics/diagnostic.rs +++ b/slicec/src/diagnostics/diagnostic.rs @@ -118,18 +118,6 @@ pub enum DiagnosticKind { Lint(Lint), } -impl From for DiagnosticKind { - fn from(error: Error) -> Self { - DiagnosticKind::Error(error) - } -} - -impl From for DiagnosticKind { - fn from(lint: Lint) -> Self { - DiagnosticKind::Lint(lint) - } -} - /// Diagnostic levels describe the severity of a diagnostic, and how the compiler should react to their emission. #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum DiagnosticLevel { From 0766cb9eceeddd1f942e7ed033655f3e577203d7 Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Wed, 15 Apr 2026 11:04:55 -0400 Subject: [PATCH 7/9] Update test messages. --- slicec/tests/diagnostic_output_tests.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/slicec/tests/diagnostic_output_tests.rs b/slicec/tests/diagnostic_output_tests.rs index 6c5e5e4b1..5cb5c80c8 100644 --- a/slicec/tests/diagnostic_output_tests.rs +++ b/slicec/tests/diagnostic_output_tests.rs @@ -38,7 +38,7 @@ mod output { // Assert let expected = concat!( - r#"{"message":"comment has a 'param' tag for 'x', but operation 'op' has no parameter with that name","severity":"warning","span":{"start":{"row":5,"col":17},"end":{"row":5,"col":25},"file":"string-0"},"notes":[],"error_code":"IncorrectDocComment"}"#, + r#"{"message":"incorrect doc comment: comment has a 'param' tag for 'x', but operation 'op' has no parameter with that name","severity":"warning","span":{"start":{"row":5,"col":17},"end":{"row":5,"col":25},"file":"string-0"},"notes":[],"error_code":"IncorrectDocComment"}"#, "\n", r#"{"message":"invalid enum 'E': enums must contain at least one enumerator","severity":"error","span":{"start":{"row":9,"col":9},"end":{"row":9,"col":15},"file":"string-0"},"notes":[],"error_code":"E008"}"#, "\n", @@ -82,7 +82,7 @@ mod output { // Assert let expected = "\ -warning [IncorrectDocComment]: comment has a 'param' tag for 'x', but operation 'op1' has no parameter with that name +warning [IncorrectDocComment]: incorrect doc comment: comment has a 'param' tag for 'x', but operation 'op1' has no parameter with that name --> string-0:5:17 | 5 | /// @param x: this is an x @@ -172,7 +172,7 @@ error [E008]: invalid enum 'E': enums must contain at least one enumerator // Assert: Only one of the two lints should be allowed. let expected = concat!( - r#"{"message":"comment has a 'param' tag for 'x', but operation 'op' has no parameter with that name","severity":"warning","span":{"start":{"row":6,"col":21},"end":{"row":6,"col":29},"file":"string-0"},"notes":[],"error_code":"IncorrectDocComment"}"#, + r#"{"message":"incorrect doc comment: comment has a 'param' tag for 'x', but operation 'op' has no parameter with that name","severity":"warning","span":{"start":{"row":6,"col":21},"end":{"row":6,"col":29},"file":"string-0"},"notes":[],"error_code":"IncorrectDocComment"}"#, "\n", ); assert_eq!(expected, String::from_utf8(output).unwrap()); From 373a9f113849e176bf3bedf0c327bdb8ce22a614 Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Wed, 15 Apr 2026 11:14:57 -0400 Subject: [PATCH 8/9] Remove trailing comma Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- slicec/src/diagnostics/errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slicec/src/diagnostics/errors.rs b/slicec/src/diagnostics/errors.rs index 5b2df57ef..e98b0710f 100644 --- a/slicec/src/diagnostics/errors.rs +++ b/slicec/src/diagnostics/errors.rs @@ -306,7 +306,7 @@ impl Error { Self::EnumUnderlyingTypeNotSupported { enum_identifier, kind } => { if let Some(kind) = kind { - format!("invalid enum '{enum_identifier}': underlying type '{kind}' is not supported", ) + format!("invalid enum '{enum_identifier}': underlying type '{kind}' is not supported") } else { format!("invalid enum '{enum_identifier}': missing required underlying type") } From 28e12533ff99748c2eb8b3d98417f9dc2a3c2cab Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Wed, 15 Apr 2026 12:05:04 -0400 Subject: [PATCH 9/9] Use better constructor names. --- slicec/src/diagnostics/diagnostic.rs | 4 +- slicec/src/grammar/attributes/allow.rs | 2 +- slicec/src/grammar/attributes/compress.rs | 2 +- slicec/src/grammar/attributes/mod.rs | 4 +- .../src/grammar/attributes/sliced_format.rs | 2 +- slicec/src/main.rs | 4 +- slicec/src/parsers/comments/mod.rs | 7 +-- slicec/src/parsers/mod.rs | 2 +- slicec/src/parsers/preprocessor/mod.rs | 6 +-- slicec/src/parsers/slice/grammar.rs | 15 ++++--- slicec/src/parsers/slice/mod.rs | 6 +-- slicec/src/patchers/comment_link_patcher.rs | 2 +- slicec/src/patchers/mod.rs | 2 +- slicec/src/patchers/type_ref_patcher.rs | 6 +-- slicec/src/utils/file_util.rs | 16 +++---- slicec/src/validators/attribute.rs | 2 +- slicec/src/validators/comments.rs | 2 +- slicec/src/validators/cycle_detection.rs | 2 +- slicec/src/validators/dictionary.rs | 10 ++--- slicec/src/validators/enums.rs | 18 ++++---- slicec/src/validators/identifiers.rs | 4 +- slicec/src/validators/members.rs | 4 +- slicec/src/validators/operations.rs | 8 ++-- slicec/src/validators/parameters.rs | 4 +- slicec/src/validators/structs.rs | 4 +- slicec/src/validators/type_aliases.rs | 2 +- slicec/tests/attribute_tests.rs | 44 +++++++++---------- slicec/tests/comment_tests.rs | 26 +++++------ slicec/tests/cycle_tests.rs | 42 +++++++++--------- slicec/tests/dictionaries/key_type.rs | 12 ++--- slicec/tests/dictionaries/value_type.rs | 4 +- slicec/tests/enums/container.rs | 32 +++++++------- slicec/tests/enums/mod.rs | 8 ++-- slicec/tests/files/io.rs | 4 +- slicec/tests/identifier_tests.rs | 4 +- slicec/tests/interfaces/inheritance.rs | 4 +- slicec/tests/interfaces/mod.rs | 2 +- slicec/tests/interfaces/operations.rs | 12 ++--- slicec/tests/module_tests.rs | 2 +- slicec/tests/parser_tests.rs | 6 +-- slicec/tests/preprocessor_tests.rs | 8 ++-- slicec/tests/redefinition_tests.rs | 24 +++++----- slicec/tests/scope_resolution_tests.rs | 4 +- slicec/tests/sequence_tests.rs | 2 +- slicec/tests/structs/container.rs | 4 +- slicec/tests/structs/tags.rs | 2 +- slicec/tests/tag_tests.rs | 12 ++--- slicec/tests/typealias_tests.rs | 2 +- 48 files changed, 201 insertions(+), 199 deletions(-) diff --git a/slicec/src/diagnostics/diagnostic.rs b/slicec/src/diagnostics/diagnostic.rs index 001f6e820..c85e2695a 100644 --- a/slicec/src/diagnostics/diagnostic.rs +++ b/slicec/src/diagnostics/diagnostic.rs @@ -37,13 +37,13 @@ impl Diagnostic { /// Creates a new error `Diagnostic` from the provided [`Error`]. /// The newly created `Diagnostic` has no `span`, `scope`, or `notes` set. - pub fn error(error: Error) -> Self { + pub fn from_error(error: Error) -> Self { Self::new(DiagnosticKind::Error(error)) } /// Creates a new lint `Diagnostic` from the provided [`Lint`]. /// The newly created `Diagnostic` has no `span`, `scope`, or `notes` set. - pub fn lint(lint: Lint) -> Self { + pub fn from_lint(lint: Lint) -> Self { Self::new(DiagnosticKind::Lint(lint)) } diff --git a/slicec/src/grammar/attributes/allow.rs b/slicec/src/grammar/attributes/allow.rs index da6103e5f..48562f2e0 100644 --- a/slicec/src/grammar/attributes/allow.rs +++ b/slicec/src/grammar/attributes/allow.rs @@ -34,7 +34,7 @@ impl Allow { // Report an error if the argument wasn't valid. if !is_valid { // TODO we should emit a link to the lint page when we write it! - let mut error = Diagnostic::error(Error::InvalidAttributeArgument { + let mut error = Diagnostic::from_error(Error::InvalidAttributeArgument { directive: "allow".to_owned(), argument: arg.to_owned(), }) diff --git a/slicec/src/grammar/attributes/compress.rs b/slicec/src/grammar/attributes/compress.rs index 3ffb79b8c..2aa792d99 100644 --- a/slicec/src/grammar/attributes/compress.rs +++ b/slicec/src/grammar/attributes/compress.rs @@ -20,7 +20,7 @@ impl Compress { "Args" => compress_args = true, "Return" => compress_return = true, _ => { - Diagnostic::error(Error::InvalidAttributeArgument { + Diagnostic::from_error(Error::InvalidAttributeArgument { directive: Self::directive().to_owned(), argument: arg.clone(), }) diff --git a/slicec/src/grammar/attributes/mod.rs b/slicec/src/grammar/attributes/mod.rs index c7f4c034c..6090f4aee 100644 --- a/slicec/src/grammar/attributes/mod.rs +++ b/slicec/src/grammar/attributes/mod.rs @@ -84,7 +84,7 @@ fn report_invalid_attribute( note: Option<&str>, diagnostics: &mut Diagnostics, ) { - let mut diagnostic = Diagnostic::error(Error::InvalidAttribute { + let mut diagnostic = Diagnostic::from_error(Error::InvalidAttribute { directive: attribute.directive().to_owned(), }) .set_span(span); @@ -113,7 +113,7 @@ fn check_argument_count_is_within( diagnostics: &mut Diagnostics, ) { if !range.contains(&arguments.len()) { - Diagnostic::error(Error::IncorrectAttributeArgumentCount { + Diagnostic::from_error(Error::IncorrectAttributeArgumentCount { directive: directive.to_owned(), expected_count: range, actual_count: arguments.len(), diff --git a/slicec/src/grammar/attributes/sliced_format.rs b/slicec/src/grammar/attributes/sliced_format.rs index 03b267d8f..0709fec6a 100644 --- a/slicec/src/grammar/attributes/sliced_format.rs +++ b/slicec/src/grammar/attributes/sliced_format.rs @@ -20,7 +20,7 @@ impl SlicedFormat { "Args" => sliced_args = true, "Return" => sliced_return = true, _ => { - Diagnostic::error(Error::InvalidAttributeArgument { + Diagnostic::from_error(Error::InvalidAttributeArgument { directive: Self::directive().to_owned(), argument: arg.clone(), }) diff --git a/slicec/src/main.rs b/slicec/src/main.rs index 28fe69506..d8ceacc93 100644 --- a/slicec/src/main.rs +++ b/slicec/src/main.rs @@ -130,7 +130,7 @@ fn handle_generator_response(response_payload: Vec, output_dir: &Option Diagnostic { let converted = Lint::MalformedDocComment { message: parse_error_kind.to_string(), }; - Diagnostic::lint(converted).set_span(&Span::new(start, end, file_name)) + Diagnostic::from_lint(converted).set_span(&Span::new(start, end, file_name)) } // The parser encountered a token that didn't fit any grammar rule. @@ -34,13 +34,14 @@ fn construct_lint_from(parse_error: ParseError, file_name: &str) -> Diagnostic { } => { // TODO: should use Display like in Slice parser. let message = generate_message(&expected, token_kind); - Diagnostic::lint(Lint::MalformedDocComment { message }).set_span(&Span::new(start, end, file_name)) + Diagnostic::from_lint(Lint::MalformedDocComment { message }).set_span(&Span::new(start, end, file_name)) } // The parser hit EOF in the middle of a grammar rule. ParseError::UnrecognizedEof { location, expected } => { let message = generate_message(&expected, "EOF"); - Diagnostic::lint(Lint::MalformedDocComment { message }).set_span(&Span::new(location, location, file_name)) + Diagnostic::from_lint(Lint::MalformedDocComment { message }) + .set_span(&Span::new(location, location, file_name)) } _ => unreachable!("impossible error encountered in comment parser: {parse_error:?}"), diff --git a/slicec/src/parsers/mod.rs b/slicec/src/parsers/mod.rs index 56ee350b1..442ee4a51 100644 --- a/slicec/src/parsers/mod.rs +++ b/slicec/src/parsers/mod.rs @@ -40,7 +40,7 @@ fn parse_file(file: &mut SliceFile, ast: &mut Ast, diagnostics: &mut Diagnostics // Issue a syntax error if the user had definitions but forgot to declare a module. if !definitions.is_empty() && module.is_none() { - Diagnostic::error(Error::Syntax { + Diagnostic::from_error(Error::Syntax { // TODO improve this message, see: #348 message: "module declaration is required".to_owned(), }) diff --git a/slicec/src/parsers/preprocessor/mod.rs b/slicec/src/parsers/preprocessor/mod.rs index 174ff6568..5aac172b9 100644 --- a/slicec/src/parsers/preprocessor/mod.rs +++ b/slicec/src/parsers/preprocessor/mod.rs @@ -27,7 +27,7 @@ fn construct_error_from(parse_error: ParseError, file_name: &str) -> Diagnostic let converted = Error::Syntax { message: parse_error_kind.to_string(), }; - Diagnostic::error(converted).set_span(&Span::new(start, end, file_name)) + Diagnostic::from_error(converted).set_span(&Span::new(start, end, file_name)) } // The parser encountered a token that didn't fit any grammar rule. @@ -36,13 +36,13 @@ fn construct_error_from(parse_error: ParseError, file_name: &str) -> Diagnostic expected, } => { let message = generate_message(&expected, token_kind); - Diagnostic::error(Error::Syntax { message }).set_span(&Span::new(start, end, file_name)) + Diagnostic::from_error(Error::Syntax { message }).set_span(&Span::new(start, end, file_name)) } // The parser hit EOF in the middle of a grammar rule. ParseError::UnrecognizedEof { location, expected } => { let message = generate_message(&expected, "EOF"); - Diagnostic::error(Error::Syntax { message }).set_span(&Span::new(location, location, file_name)) + Diagnostic::from_error(Error::Syntax { message }).set_span(&Span::new(location, location, file_name)) } // Only the built-in lexer emits 'InvalidToken' errors. We use our own lexer so this is impossible. diff --git a/slicec/src/parsers/slice/grammar.rs b/slicec/src/parsers/slice/grammar.rs index c524fa336..91566f158 100644 --- a/slicec/src/parsers/slice/grammar.rs +++ b/slicec/src/parsers/slice/grammar.rs @@ -64,10 +64,11 @@ fn construct_module( span: Span, ) -> OwnedPtr { if !raw_comment.is_empty() { - let error = Error::Syntax { + Diagnostic::from_error(Error::Syntax { message: "doc comments cannot be applied to modules".to_owned(), - }; - Diagnostic::error(error).set_span(&span).push_into(parser.diagnostics); + }) + .set_span(&span) + .push_into(parser.diagnostics); } let module_ptr = OwnedPtr::new(Module { @@ -203,7 +204,7 @@ fn construct_parameter( span: Span, ) -> OwnedPtr { if !raw_comment.is_empty() { - Diagnostic::error(Error::Syntax { + Diagnostic::from_error(Error::Syntax { message: "doc comments cannot be applied to parameters".to_owned(), }) .set_span(&span) @@ -251,7 +252,7 @@ fn construct_single_return_type( fn check_return_tuple(parser: &mut Parser, return_tuple: &[OwnedPtr], span: Span) { if return_tuple.len() < 2 { - let diagnostic = Diagnostic::error(Error::ReturnTuplesMustContainAtLeastTwoElements).set_span(&span); + let diagnostic = Diagnostic::from_error(Error::ReturnTuplesMustContainAtLeastTwoElements).set_span(&span); diagnostic.push_into(parser.diagnostics); } } @@ -454,7 +455,7 @@ fn try_parse_integer(parser: &mut Parser, s: &str, span: Span) -> Integer IntErrorKind::InvalidDigit => Error::InvalidIntegerLiteral { base }, _ => Error::IntegerLiteralOverflows, }; - Diagnostic::error(e).set_span(&span).push_into(parser.diagnostics); + Diagnostic::from_error(e).set_span(&span).push_into(parser.diagnostics); 0 // Dummy value } }; @@ -465,7 +466,7 @@ fn try_parse_integer(parser: &mut Parser, s: &str, span: Span) -> Integer fn parse_tag_value(parser: &mut Parser, i: Integer) -> Integer { // Verify that the provided integer is a valid tag id. if !RangeInclusive::new(0, i32::MAX as i128).contains(&i.value) { - let diagnostic = Diagnostic::error(Error::TagValueOutOfBounds).set_span(&i.span); + let diagnostic = Diagnostic::from_error(Error::TagValueOutOfBounds).set_span(&i.span); diagnostic.push_into(parser.diagnostics); } diff --git a/slicec/src/parsers/slice/mod.rs b/slicec/src/parsers/slice/mod.rs index 05fe961a9..5e5a8c6c3 100644 --- a/slicec/src/parsers/slice/mod.rs +++ b/slicec/src/parsers/slice/mod.rs @@ -24,7 +24,7 @@ fn construct_error_from(parse_error: ParseError, file_name: &str) -> Diagnostic let converted = Error::Syntax { message: parse_error_kind.to_string(), }; - Diagnostic::error(converted).set_span(&Span::new(start, end, file_name)) + Diagnostic::from_error(converted).set_span(&Span::new(start, end, file_name)) } // The parser encountered a token that didn't fit any grammar rule. @@ -33,13 +33,13 @@ fn construct_error_from(parse_error: ParseError, file_name: &str) -> Diagnostic expected, } => { let message = generate_message(&expected, token_kind); - Diagnostic::error(Error::Syntax { message }).set_span(&Span::new(start, end, file_name)) + Diagnostic::from_error(Error::Syntax { message }).set_span(&Span::new(start, end, file_name)) } // The parser hit EOF in the middle of a grammar rule. ParseError::UnrecognizedEof { location, expected } => { let message = generate_message(&expected, "EOF"); - Diagnostic::error(Error::Syntax { message }).set_span(&Span::new(location, location, file_name)) + Diagnostic::from_error(Error::Syntax { message }).set_span(&Span::new(location, location, file_name)) } _ => unreachable!("impossible error encountered in Slice parser: '{parse_error:?}'"), diff --git a/slicec/src/patchers/comment_link_patcher.rs b/slicec/src/patchers/comment_link_patcher.rs index a92bd6983..0a537d473 100644 --- a/slicec/src/patchers/comment_link_patcher.rs +++ b/slicec/src/patchers/comment_link_patcher.rs @@ -115,7 +115,7 @@ impl CommentLinkPatcher<'_> { self.link_patches.push_back(match result { Ok(ptr) => Some(ptr), Err(message) => { - Diagnostic::lint(Lint::BrokenDocLink { message }) + Diagnostic::from_lint(Lint::BrokenDocLink { message }) .set_span(identifier.span()) .set_scope(commentable.parser_scoped_identifier()) .push_into(self.diagnostics); diff --git a/slicec/src/patchers/mod.rs b/slicec/src/patchers/mod.rs index e493b93ca..affe25578 100644 --- a/slicec/src/patchers/mod.rs +++ b/slicec/src/patchers/mod.rs @@ -45,7 +45,7 @@ macro_rules! patch_attributes { // If the directive starts with the provided prefix, but didn't match a known attribute. let directive_prefix = directive.split_once("::").map_or("", |(p, _)| p); if $prefix == directive_prefix { - Diagnostic::error(Error::UnknownAttribute { + Diagnostic::from_error(Error::UnknownAttribute { directive: directive.to_owned(), }) .set_span(attribute.span()) diff --git a/slicec/src/patchers/type_ref_patcher.rs b/slicec/src/patchers/type_ref_patcher.rs index 1a46a79e4..5b73166a3 100644 --- a/slicec/src/patchers/type_ref_patcher.rs +++ b/slicec/src/patchers/type_ref_patcher.rs @@ -190,7 +190,7 @@ impl TypeRefPatcher<'_> { is_concrete, }, }; - Diagnostic::error(mapped_error) + Diagnostic::from_error(mapped_error) .set_span(identifier.span()) .push_into(self.diagnostics); None @@ -207,7 +207,7 @@ impl TypeRefPatcher<'_> { // only check the first argument. If it's present, we attach it to the lint message. let identifier = entity.identifier().to_owned(); let reason = deprecated.reason.clone(); - Diagnostic::lint(Lint::Deprecated { identifier, reason }) + Diagnostic::from_lint(Lint::Deprecated { identifier, reason }) .set_span(type_ref.span()) .set_scope(type_ref.parser_scope()) .add_note( @@ -243,7 +243,7 @@ impl TypeRefPatcher<'_> { // an error for it. This check makes sure we don't report errors for type aliases that aren't cyclic, // but use another type-alias which is. In this case, the chain contains it, but it won't be the first. if type_alias_chain.first() == Some(&type_alias_id) { - Diagnostic::error(Error::SelfReferentialTypeAliasNeedsConcreteType { + Diagnostic::from_error(Error::SelfReferentialTypeAliasNeedsConcreteType { identifier: current_type_alias.module_scoped_identifier(), }) .set_span(current_type_alias.span()) diff --git a/slicec/src/utils/file_util.rs b/slicec/src/utils/file_util.rs index b42197f13..ffebac8fe 100644 --- a/slicec/src/utils/file_util.rs +++ b/slicec/src/utils/file_util.rs @@ -42,7 +42,7 @@ fn remove_duplicate_file_paths(file_paths: Vec, diagnostics: &mut Diag for file_path in file_paths { if deduped_file_paths.contains(&file_path) { let lint = Lint::DuplicateFile { path: file_path.path }; - Diagnostic::lint(lint).push_into(diagnostics); + Diagnostic::from_lint(lint).push_into(diagnostics); } else { deduped_file_paths.push(file_path); } @@ -73,7 +73,7 @@ pub fn resolve_files_from(options: &SliceOptions, diagnostics: &mut Diagnostics) for file_path in file_paths { match fs::read_to_string(&file_path.path) { Ok(raw_text) => files.push(SliceFile::new(file_path.path, raw_text, file_path.is_source)), - Err(error) => Diagnostic::error(Error::IO { + Err(error) => Diagnostic::from_error(Error::IO { action: "read", path: file_path.path, error, @@ -94,7 +94,7 @@ fn find_slice_files(paths: &[String], are_source_files: bool, diagnostics: &mut // If the path does not exist, report an error and continue. if !path_buf.exists() { - Diagnostic::error(Error::IO { + Diagnostic::from_error(Error::IO { action: "read", path: path.to_owned(), error: io::ErrorKind::NotFound.into(), @@ -110,7 +110,7 @@ fn find_slice_files(paths: &[String], are_source_files: bool, diagnostics: &mut io::ErrorKind::InvalidFilename, "Slice files must end with a '.slice' extension", ); - Diagnostic::error(Error::IO { + Diagnostic::from_error(Error::IO { action: "read", path: path.to_owned(), error: io_error, @@ -126,7 +126,7 @@ fn find_slice_files(paths: &[String], are_source_files: bool, diagnostics: &mut io::ErrorKind::InvalidFilename, "Expected a Slice file but found a directory.", ); - Diagnostic::error(Error::IO { + Diagnostic::from_error(Error::IO { action: "read", path: path.to_owned(), error: io_error, @@ -144,7 +144,7 @@ fn find_slice_files(paths: &[String], are_source_files: bool, diagnostics: &mut .filter_map(|path| match FilePath::try_create(&path, are_source_files) { Ok(file_path) => Some(file_path), Err(error) => { - Diagnostic::error(Error::IO { + Diagnostic::from_error(Error::IO { action: "read", path, error, @@ -162,7 +162,7 @@ fn find_slice_files_in_path(path: PathBuf, diagnostics: &mut Diagnostics) -> Vec // Recurse into the directory. match find_slice_files_in_directory(&path, diagnostics) { Ok(child_paths) => paths.extend(child_paths), - Err(error) => Diagnostic::error(Error::IO { + Err(error) => Diagnostic::from_error(Error::IO { action: "read", path: path.display().to_string(), error, @@ -188,7 +188,7 @@ fn find_slice_files_in_directory(path: &Path, diagnostics: &mut Diagnostics) -> Ok(child) => paths.extend(find_slice_files_in_path(child.path(), diagnostics)), Err(error) => { // If we cannot read the directory entry, report an error and continue. - Diagnostic::error(Error::IO { + Diagnostic::from_error(Error::IO { action: "read", path: path.display().to_string(), error, diff --git a/slicec/src/validators/attribute.rs b/slicec/src/validators/attribute.rs index b0f89ab36..681efafb3 100644 --- a/slicec/src/validators/attribute.rs +++ b/slicec/src/validators/attribute.rs @@ -29,7 +29,7 @@ pub fn validate_repeated_attributes(attributes: &[&Attribute], diagnostics: &mut match first_attribute_occurrence.entry(directive) { Occupied(entry) => { - Diagnostic::error(Error::AttributeIsNotRepeatable { + Diagnostic::from_error(Error::AttributeIsNotRepeatable { directive: directive.to_owned(), }) .set_span(span) diff --git a/slicec/src/validators/comments.rs b/slicec/src/validators/comments.rs index a5eadd191..1e5db6b2c 100644 --- a/slicec/src/validators/comments.rs +++ b/slicec/src/validators/comments.rs @@ -51,7 +51,7 @@ fn report_only_operation_error( _ => unreachable!("'report_only_operation_error' was called with unsupported tag '{tag_kind}'"), }; - Diagnostic::lint(Lint::IncorrectDocComment { + Diagnostic::from_lint(Lint::IncorrectDocComment { message: format!("comment has a '{tag_kind}' tag, but only operations can {action_phrase}"), }) .set_span(&(tag.span() + message_span)) diff --git a/slicec/src/validators/cycle_detection.rs b/slicec/src/validators/cycle_detection.rs index fc271bc03..cd869968c 100644 --- a/slicec/src/validators/cycle_detection.rs +++ b/slicec/src/validators/cycle_detection.rs @@ -147,7 +147,7 @@ impl<'a> CycleDetector<'a> { let cycle_notes = self.dependency_stack.iter().map(|(_, field)| Self::get_note_for(field)); // Report the error. - Diagnostic::error(Error::InfiniteSizeCycle { type_id, cycle }) + Diagnostic::from_error(Error::InfiniteSizeCycle { type_id, cycle }) .set_span(type_being_checked.1.span()) .extend_notes(cycle_notes) .push_into(self.diagnostics); diff --git a/slicec/src/validators/dictionary.rs b/slicec/src/validators/dictionary.rs index ce0c49951..b9b10370c 100644 --- a/slicec/src/validators/dictionary.rs +++ b/slicec/src/validators/dictionary.rs @@ -16,7 +16,7 @@ fn has_allowed_key_type(dictionary: &Dictionary, diagnostics: &mut Diagnostics) fn check_dictionary_key_type(type_ref: &TypeRef) -> Option { // Optional types cannot be used as dictionary keys. if type_ref.is_optional { - return Some(Diagnostic::error(Error::KeyMustBeNonOptional).set_span(type_ref.span())); + return Some(Diagnostic::from_error(Error::KeyMustBeNonOptional).set_span(type_ref.span())); } let definition = type_ref.definition(); @@ -24,7 +24,7 @@ fn check_dictionary_key_type(type_ref: &TypeRef) -> Option { Types::Struct(struct_def) => { // Only compact structs can be used for dictionary keys. if !struct_def.is_compact { - return Some(Diagnostic::error(Error::StructKeyMustBeCompact).set_span(type_ref.span())); + return Some(Diagnostic::from_error(Error::StructKeyMustBeCompact).set_span(type_ref.span())); } // Check that all the fields of the struct are also valid key types. @@ -35,7 +35,7 @@ fn check_dictionary_key_type(type_ref: &TypeRef) -> Option { .filter_map(|field| check_dictionary_key_type(field.data_type())) .collect::>(); if !errors.is_empty() { - let mut error = Diagnostic::error(Error::StructKeyContainsDisallowedType { + let mut error = Diagnostic::from_error(Error::StructKeyContainsDisallowedType { struct_identifier: struct_def.identifier().to_owned(), }) .set_span(type_ref.span()); @@ -52,7 +52,7 @@ fn check_dictionary_key_type(type_ref: &TypeRef) -> Option { // Only enums with underlying types can be used as dictionary keys. Fields aren't allowed. Types::Enum(enum_def) => { if enum_def.underlying.is_none() { - let error = Diagnostic::error(Error::KeyTypeNotSupported { + let error = Diagnostic::from_error(Error::KeyTypeNotSupported { kind: formatted_kind(definition), }) .set_span(type_ref.span()) @@ -73,7 +73,7 @@ fn check_dictionary_key_type(type_ref: &TypeRef) -> Option { if !is_valid { return Some( - Diagnostic::error(Error::KeyTypeNotSupported { + Diagnostic::from_error(Error::KeyTypeNotSupported { kind: formatted_kind(definition), }) .set_span(type_ref.span()), diff --git a/slicec/src/validators/enums.rs b/slicec/src/validators/enums.rs index 5856cc2fd..8e8bc3789 100644 --- a/slicec/src/validators/enums.rs +++ b/slicec/src/validators/enums.rs @@ -33,7 +33,7 @@ fn backing_type_bounds(enum_def: &Enum, diagnostics: &mut Diagnostics) { min, max, }; - Diagnostic::error(error) + Diagnostic::from_error(error) .set_span(enumerator.span()) .push_into(diagnostics); }); @@ -57,7 +57,7 @@ fn backing_type_bounds(enum_def: &Enum, diagnostics: &mut Diagnostics) { fn allowed_underlying_types(enum_def: &Enum, diagnostics: &mut Diagnostics) { if let Some(underlying_type) = &enum_def.underlying { if !underlying_type.is_integral() { - Diagnostic::error(Error::EnumUnderlyingTypeNotSupported { + Diagnostic::from_error(Error::EnumUnderlyingTypeNotSupported { enum_identifier: enum_def.identifier().to_owned(), kind: Some(underlying_type.definition().kind().to_owned()), }) @@ -74,7 +74,7 @@ fn enumerator_values_are_unique(enum_def: &Enum, diagnostics: &mut Diagnostics) // If the value is already in the map, another enumerator already used it. Get that enumerator from the map // and report an error. Otherwise add the enumerator and its value to the map. if let Some(alt_enum) = value_to_enumerator_map.get(&enumerator.value()) { - Diagnostic::error(Error::DuplicateEnumeratorValue { + Diagnostic::from_error(Error::DuplicateEnumeratorValue { enumerator_value: enumerator.value(), }) .set_span(enumerator.span()) @@ -93,7 +93,7 @@ fn enumerator_values_are_unique(enum_def: &Enum, diagnostics: &mut Diagnostics) fn underlying_type_cannot_be_optional(enum_def: &Enum, diagnostics: &mut Diagnostics) { if let Some(ref typeref) = enum_def.underlying { if typeref.is_optional { - Diagnostic::error(Error::CannotUseOptionalUnderlyingType { + Diagnostic::from_error(Error::CannotUseOptionalUnderlyingType { enum_identifier: enum_def.identifier().to_owned(), }) .set_span(enum_def.span()) @@ -105,7 +105,7 @@ fn underlying_type_cannot_be_optional(enum_def: &Enum, diagnostics: &mut Diagnos /// Validate that a checked enum must not be empty. fn nonempty_if_checked(enum_def: &Enum, diagnostics: &mut Diagnostics) { if !enum_def.is_unchecked && enum_def.enumerators.is_empty() { - Diagnostic::error(Error::MustContainEnumerators { + Diagnostic::from_error(Error::MustContainEnumerators { enum_identifier: enum_def.identifier().to_owned(), }) .set_span(enum_def.span()) @@ -120,7 +120,7 @@ fn cannot_contain_fields(enum_def: &Enum, diagnostics: &mut Diagnostics) { for enumerator in enum_def.enumerators() { if enumerator.fields.is_some() { - Diagnostic::error(Error::EnumeratorCannotContainFields { + Diagnostic::from_error(Error::EnumeratorCannotContainFields { enumerator_identifier: enumerator.identifier().to_owned(), }) .set_span(enumerator.span()) @@ -137,7 +137,7 @@ fn cannot_contain_fields(enum_def: &Enum, diagnostics: &mut Diagnostics) { fn check_compact_modifier(enum_def: &Enum, diagnostics: &mut Diagnostics) { if enum_def.is_compact { if let Some(underlying) = &enum_def.underlying { - Diagnostic::error(Error::CannotBeCompact { + Diagnostic::from_error(Error::CannotBeCompact { kind: enum_def.kind(), identifier: enum_def.identifier().to_owned(), }) @@ -150,7 +150,7 @@ fn check_compact_modifier(enum_def: &Enum, diagnostics: &mut Diagnostics) { } if enum_def.is_unchecked { - Diagnostic::error(Error::CannotBeCompact { + Diagnostic::from_error(Error::CannotBeCompact { kind: enum_def.kind(), identifier: enum_def.identifier().to_owned(), }) @@ -170,7 +170,7 @@ fn compact_enums_cannot_contain_tags(enum_def: &Enum, diagnostics: &mut Diagnost for enumerator in enum_def.enumerators() { for field in enumerator.fields() { if field.is_tagged() { - Diagnostic::error(Error::CompactTypeCannotContainTaggedFields { kind: enum_def.kind() }) + Diagnostic::from_error(Error::CompactTypeCannotContainTaggedFields { kind: enum_def.kind() }) .set_span(field.span()) .add_note( format!("enum '{}' is declared compact here", enum_def.identifier()), diff --git a/slicec/src/validators/identifiers.rs b/slicec/src/validators/identifiers.rs index 420e9a07d..9bcd8ced3 100644 --- a/slicec/src/validators/identifiers.rs +++ b/slicec/src/validators/identifiers.rs @@ -27,7 +27,7 @@ fn check_for_shadowing( for identifier in identifiers { for inherited_identifier in &inherited_identifiers { if identifier.value == inherited_identifier.value { - Diagnostic::error(Error::Shadows { + Diagnostic::from_error(Error::Shadows { identifier: identifier.value.clone(), }) .set_span(identifier.span()) @@ -118,7 +118,7 @@ impl<'a> RedefinitionChecker<'a> { } fn report_redefinition_error(&mut self, new: &dyn NamedSymbol, original: &dyn NamedSymbol) { - Diagnostic::error(Error::Redefinition { + Diagnostic::from_error(Error::Redefinition { identifier: new.identifier().to_owned(), }) .set_span(new.raw_identifier().span()) diff --git a/slicec/src/validators/members.rs b/slicec/src/validators/members.rs index cbef6a17e..320fe7d2e 100644 --- a/slicec/src/validators/members.rs +++ b/slicec/src/validators/members.rs @@ -17,7 +17,7 @@ fn tags_are_unique(members: Vec<&impl Member>, diagnostics: &mut Diagnostics) { sorted_tagged_members.sort_by_key(|member| member.tag().expect("tagged member has no tag!")); sorted_tagged_members.windows(2).for_each(|window| { if window[0].tag() == window[1].tag() { - Diagnostic::error(Error::CannotHaveDuplicateTag { + Diagnostic::from_error(Error::CannotHaveDuplicateTag { identifier: window[1].identifier().to_owned(), }) .set_span(window[1].span()) @@ -41,7 +41,7 @@ fn tags_have_optional_types(members: Vec<&impl Member>, diagnostics: &mut Diagno // Validate that tagged members are optional. for member in tagged_members { if !member.data_type().is_optional { - Diagnostic::error(Error::TaggedMemberMustBeOptional { + Diagnostic::from_error(Error::TaggedMemberMustBeOptional { identifier: member.identifier().to_owned(), }) .set_span(member.span()) diff --git a/slicec/src/validators/operations.rs b/slicec/src/validators/operations.rs index a20aa2212..b858fec69 100644 --- a/slicec/src/validators/operations.rs +++ b/slicec/src/validators/operations.rs @@ -16,7 +16,7 @@ fn validate_param_tags(comment: &DocComment, operation: &Operation, diagnostics: for param_tag in &comment.params { let tag_identifier = param_tag.identifier.value.as_str(); if !parameters.contains(&tag_identifier) { - Diagnostic::lint(Lint::IncorrectDocComment { + Diagnostic::from_lint(Lint::IncorrectDocComment { message: format!( "comment has a 'param' tag for '{tag_identifier}', but operation '{}' has no parameter with that name", operation.identifier(), @@ -49,7 +49,7 @@ fn validate_returns_tags_for_operation_with_no_return_type( diagnostics: &mut Diagnostics, ) { for returns_tag in returns_tags { - Diagnostic::lint(Lint::IncorrectDocComment { + Diagnostic::from_lint(Lint::IncorrectDocComment { message: format!( "comment has a 'returns' tag, but operation '{}' does not return anything", operation.identifier(), @@ -68,7 +68,7 @@ fn validate_returns_tags_for_operation_with_single_return( ) { for returns_tag in returns_tags { if let Some(tag_identifier) = &returns_tag.identifier { - Diagnostic::lint(Lint::IncorrectDocComment { + Diagnostic::from_lint(Lint::IncorrectDocComment { message: format!( "comment has a 'returns' tag for '{}', but operation '{}' doesn't return anything with that name", &tag_identifier.value, @@ -99,7 +99,7 @@ fn validate_returns_tags_for_operation_with_return_tuple( if let Some(tag_identifier) = &returns_tag.identifier { let tag_identifier = tag_identifier.value.as_str(); if !return_members.contains(&tag_identifier) { - Diagnostic::lint(Lint::IncorrectDocComment { + Diagnostic::from_lint(Lint::IncorrectDocComment { message: format!( "comment has a 'returns' tag for '{tag_identifier}', but operation '{}' doesn't return anything with that name", operation.identifier(), diff --git a/slicec/src/validators/parameters.rs b/slicec/src/validators/parameters.rs index 73c99889f..486c5e5fb 100644 --- a/slicec/src/validators/parameters.rs +++ b/slicec/src/validators/parameters.rs @@ -15,7 +15,7 @@ fn at_most_one_stream_parameter(members: &[&Parameter], diagnostics: &mut Diagno .split_last() // Split at the last element, which is the one we do not want to report an error for. .unwrap().1 // All members before the split. Safe to unwrap since we know there are at least two members. .iter() - .for_each(|m| Diagnostic::error(Error::MultipleStreamedMembers).set_span(m.span()).push_into(diagnostics)); + .for_each(|m| Diagnostic::from_error(Error::MultipleStreamedMembers).set_span(m.span()).push_into(diagnostics)); } } @@ -26,7 +26,7 @@ fn stream_parameter_is_last(members: &[&Parameter], diagnostics: &mut Diagnostic .into_iter() .filter(|m| m.is_streamed) .for_each(|m| { - Diagnostic::error(Error::StreamedMembersMustBeLast { parameter_identifier: m.identifier().to_owned() }) + Diagnostic::from_error(Error::StreamedMembersMustBeLast { parameter_identifier: m.identifier().to_owned() }) .set_span(m.span()) .push_into(diagnostics); }); diff --git a/slicec/src/validators/structs.rs b/slicec/src/validators/structs.rs index c704a84ef..f68028add 100644 --- a/slicec/src/validators/structs.rs +++ b/slicec/src/validators/structs.rs @@ -10,7 +10,7 @@ pub fn validate_struct(struct_def: &Struct, diagnostics: &mut Diagnostics) { fn validate_compact_struct_not_empty(struct_def: &Struct, diagnostics: &mut Diagnostics) { // Compact structs must be non-empty. if struct_def.is_compact && struct_def.fields().is_empty() { - Diagnostic::error(Error::CompactStructCannotBeEmpty) + Diagnostic::from_error(Error::CompactStructCannotBeEmpty) .set_span(struct_def.span()) .push_into(diagnostics); } @@ -21,7 +21,7 @@ fn compact_structs_cannot_contain_tags(struct_def: &Struct, diagnostics: &mut Di if struct_def.is_compact { for field in struct_def.fields() { if field.is_tagged() { - Diagnostic::error(Error::CompactTypeCannotContainTaggedFields { kind: struct_def.kind() }) + Diagnostic::from_error(Error::CompactTypeCannotContainTaggedFields { kind: struct_def.kind() }) .set_span(field.span()) .add_note( format!("struct '{}' is declared compact here", struct_def.identifier()), diff --git a/slicec/src/validators/type_aliases.rs b/slicec/src/validators/type_aliases.rs index a0cbcda07..65e350c77 100644 --- a/slicec/src/validators/type_aliases.rs +++ b/slicec/src/validators/type_aliases.rs @@ -9,7 +9,7 @@ pub fn validate_type_alias(type_alias: &TypeAlias, diagnostics: &mut Diagnostics fn type_aliases_cannot_be_optional(type_alias: &TypeAlias, diagnostics: &mut Diagnostics) { if type_alias.underlying.is_optional { - Diagnostic::error(Error::TypeAliasOfOptional) + Diagnostic::from_error(Error::TypeAliasOfOptional) .set_span(type_alias.span()) .add_note( "try removing the trailing `?` modifier from its definition", diff --git a/slicec/tests/attribute_tests.rs b/slicec/tests/attribute_tests.rs index ddd694c65..37f2d658f 100644 --- a/slicec/tests/attribute_tests.rs +++ b/slicec/tests/attribute_tests.rs @@ -43,7 +43,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::InvalidAttributeArgument { + let expected = Diagnostic::from_error(Error::InvalidAttributeArgument { directive: "allow".to_owned(), argument: "Fake".to_owned(), }); @@ -78,7 +78,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::IncorrectAttributeArgumentCount { + let expected = Diagnostic::from_error(Error::IncorrectAttributeArgumentCount { directive: "allow".to_owned(), expected_count: 1..usize::MAX, actual_count: 0, @@ -113,14 +113,14 @@ mod attributes { // Assert let mut all_lints = vec![ - Diagnostic::lint(Lint::Deprecated { + Diagnostic::from_lint(Lint::Deprecated { identifier: "S".to_owned(), reason: Some("test".to_owned()), }), - Diagnostic::lint(Lint::BrokenDocLink { + Diagnostic::from_lint(Lint::BrokenDocLink { message: "no element named 'fake' exists in scope".to_owned(), }), - Diagnostic::lint(Lint::IncorrectDocComment { + Diagnostic::from_lint(Lint::IncorrectDocComment { message: "comment has a 'returns' tag, but only operations can return".to_owned(), }), ]; @@ -183,7 +183,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::InvalidAttributeArgument { + let expected = Diagnostic::from_error(Error::InvalidAttributeArgument { directive: "slicedFormat".to_owned(), argument: "Foo".to_owned(), }) @@ -208,7 +208,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::InvalidAttribute { + let expected = Diagnostic::from_error(Error::InvalidAttribute { directive: "slicedFormat".to_owned(), }) .set_span(&Span::new((4, 18).into(), (4, 36).into(), "string-0")) @@ -233,7 +233,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::IncorrectAttributeArgumentCount { + let expected = Diagnostic::from_error(Error::IncorrectAttributeArgumentCount { directive: "slicedFormat".to_owned(), expected_count: 1..usize::MAX, actual_count: 0, @@ -278,7 +278,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::InvalidAttribute { + let expected = Diagnostic::from_error(Error::InvalidAttribute { directive: "deprecated".to_owned(), }) .set_span(&Span::new((5, 25).into(), (5, 35).into(), "string-0")) @@ -329,7 +329,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::lint(Lint::Deprecated { + let expected = Diagnostic::from_lint(Lint::Deprecated { identifier: "Bar".to_owned(), reason: None, }); @@ -350,7 +350,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::InvalidAttribute { + let expected = Diagnostic::from_error(Error::InvalidAttribute { directive: "deprecated".to_owned(), }); @@ -375,7 +375,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::lint(Lint::Deprecated { + let expected = Diagnostic::from_lint(Lint::Deprecated { identifier: "A".to_owned(), reason: Some("Message here".to_owned()), }); @@ -398,7 +398,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::lint(Lint::Deprecated { + let expected = Diagnostic::from_lint(Lint::Deprecated { identifier: "A".to_owned(), reason: None, }); @@ -444,7 +444,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::InvalidAttributeArgument { + let expected = Diagnostic::from_error(Error::InvalidAttributeArgument { directive: "compress".to_owned(), argument: "Foo".to_owned(), }) @@ -469,7 +469,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::InvalidAttribute { + let expected = Diagnostic::from_error(Error::InvalidAttribute { directive: "compress".to_owned(), }) .set_span(&Span::new((4, 18).into(), (4, 32).into(), "string-0")) @@ -494,7 +494,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::IncorrectAttributeArgumentCount { + let expected = Diagnostic::from_error(Error::IncorrectAttributeArgumentCount { directive: "compress".to_owned(), expected_count: 1..usize::MAX, actual_count: 0, @@ -521,7 +521,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::AttributeIsNotRepeatable { + let expected = Diagnostic::from_error(Error::AttributeIsNotRepeatable { directive: "compress".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -541,7 +541,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::InvalidAttribute { + let expected = Diagnostic::from_error(Error::InvalidAttribute { directive: "oneway".to_owned(), }); @@ -562,7 +562,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); - let expected = Diagnostic::error(Error::InvalidAttribute { + let expected = Diagnostic::from_error(Error::InvalidAttribute { directive: "deprecated".to_owned(), }); @@ -582,7 +582,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); - let expected = Diagnostic::error(Error::InvalidAttribute { + let expected = Diagnostic::from_error(Error::InvalidAttribute { directive: attribute.to_owned(), }); @@ -740,7 +740,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::UnknownAttribute { + let expected = Diagnostic::from_error(Error::UnknownAttribute { directive: directive.to_owned(), }); @@ -763,7 +763,7 @@ mod attributes { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Syntax { + let expected = Diagnostic::from_error(Error::Syntax { message: format!("expected 'identifier', but found '{found}'"), }); diff --git a/slicec/tests/comment_tests.rs b/slicec/tests/comment_tests.rs index 2f4a7f1b2..3953ac829 100644 --- a/slicec/tests/comment_tests.rs +++ b/slicec/tests/comment_tests.rs @@ -166,7 +166,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Syntax { + let expected = Diagnostic::from_error(Error::Syntax { message: "doc comments cannot be applied to modules".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -196,10 +196,10 @@ mod comments { // Assert let expected = [ - Diagnostic::error(Error::Syntax { + Diagnostic::from_error(Error::Syntax { message: "doc comments cannot be applied to parameters".to_owned(), }), - Diagnostic::error(Error::Syntax { + Diagnostic::from_error(Error::Syntax { // TODO: improve the message for return members, since they're not parameters. // We need to find an umbrella term for return members and parameters. message: "doc comments cannot be applied to parameters".to_owned(), @@ -341,7 +341,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::lint(Lint::MalformedDocComment { + let expected = Diagnostic::from_lint(Lint::MalformedDocComment { message: "unknown doc comment tag 'linked'".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -361,7 +361,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::lint(Lint::BrokenDocLink { + let expected = Diagnostic::from_lint(Lint::BrokenDocLink { message: "no element named 'OtherStruct' exists in scope".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -389,7 +389,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::lint(Lint::BrokenDocLink { + let expected = Diagnostic::from_lint(Lint::BrokenDocLink { message: format!("{kind} cannot be linked to"), }); check_diagnostics(diagnostics, [expected]); @@ -411,7 +411,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::lint(Lint::IncorrectDocComment { + let expected = Diagnostic::from_lint(Lint::IncorrectDocComment { message: "comment has a 'param' tag for 'foo', but operation 'op' has no parameter with that name" .to_owned(), }); @@ -434,7 +434,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::lint(Lint::IncorrectDocComment { + let expected = Diagnostic::from_lint(Lint::IncorrectDocComment { message: "comment has a 'param' tag for 'foo', but operation 'op' has no parameter with that name" .to_owned(), }); @@ -460,7 +460,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::lint(Lint::IncorrectDocComment { + let expected = Diagnostic::from_lint(Lint::IncorrectDocComment { message: "comment has a 'returns' tag, but operation 'op' does not return anything".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -482,7 +482,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::lint(Lint::IncorrectDocComment { + let expected = Diagnostic::from_lint(Lint::IncorrectDocComment { message: "comment has a 'returns' tag for 'foo', but operation 'op' doesn't return anything with that name" .to_owned(), }); @@ -505,7 +505,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::lint(Lint::IncorrectDocComment { + let expected = Diagnostic::from_lint(Lint::IncorrectDocComment { message: "comment has a 'returns' tag for 'foo', but operation 'op' doesn't return anything with that name" .to_owned(), }); @@ -526,7 +526,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::lint(Lint::IncorrectDocComment { + let expected = Diagnostic::from_lint(Lint::IncorrectDocComment { message: "comment has a 'param' tag, but only operations can have parameters".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -546,7 +546,7 @@ mod comments { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::lint(Lint::IncorrectDocComment { + let expected = Diagnostic::from_lint(Lint::IncorrectDocComment { message: "comment has a 'returns' tag, but only operations can return".to_owned(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/cycle_tests.rs b/slicec/tests/cycle_tests.rs index 461bf058c..e5efccdc9 100644 --- a/slicec/tests/cycle_tests.rs +++ b/slicec/tests/cycle_tests.rs @@ -23,7 +23,7 @@ mod container { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::InfiniteSizeCycle { + let expected = Diagnostic::from_error(Error::InfiniteSizeCycle { type_id: "Test::Container".to_owned(), cycle: "Test::Container -> Test::Container".to_owned(), }); @@ -49,7 +49,7 @@ mod container { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::InfiniteSizeCycle { + let expected = Diagnostic::from_error(Error::InfiniteSizeCycle { type_id: "Test::Container".to_owned(), cycle: "Test::Container -> Test::Inner -> Test::Container".to_owned(), }); @@ -75,7 +75,7 @@ mod container { let diagnostics = parse_for_diagnostics(slice); // Assert: only `Container` should be marked as cyclic here. - let expected = Diagnostic::error(Error::InfiniteSizeCycle { + let expected = Diagnostic::from_error(Error::InfiniteSizeCycle { type_id: "Test::Container".to_owned(), cycle: "Test::Container -> Test::Container".to_owned(), }); @@ -99,7 +99,7 @@ mod container { let diagnostics = parse_for_diagnostics(slice); // Assert: only one error is emitted, despite multiple cyclic paths existing. - let expected = Diagnostic::error(Error::InfiniteSizeCycle { + let expected = Diagnostic::from_error(Error::InfiniteSizeCycle { type_id: "Test::Container".to_owned(), cycle: "Test::Container -> Test::Container".to_owned(), }); @@ -122,19 +122,19 @@ mod container { // Assert: There are technically 18 cycles in the above Slice, but only 4 are unique cycles. let expected = [ - Diagnostic::error(Error::InfiniteSizeCycle { + Diagnostic::from_error(Error::InfiniteSizeCycle { type_id: "Test::A".to_owned(), cycle: "Test::A -> Test::B -> Test::A".to_owned(), }), - Diagnostic::error(Error::InfiniteSizeCycle { + Diagnostic::from_error(Error::InfiniteSizeCycle { type_id: "Test::A".to_owned(), cycle: "Test::A -> Test::B -> Test::C -> Test::A".to_owned(), }), - Diagnostic::error(Error::InfiniteSizeCycle { + Diagnostic::from_error(Error::InfiniteSizeCycle { type_id: "Test::A".to_owned(), cycle: "Test::A -> Test::C -> Test::A".to_owned(), }), - Diagnostic::error(Error::InfiniteSizeCycle { + Diagnostic::from_error(Error::InfiniteSizeCycle { type_id: "Test::B".to_owned(), cycle: "Test::B -> Test::C -> Test::B".to_owned(), }), @@ -162,7 +162,7 @@ mod builtin { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::InfiniteSizeCycle { + let expected = Diagnostic::from_error(Error::InfiniteSizeCycle { type_id: "Test::Foo".to_owned(), cycle: "Test::Foo -> Test::Foo".to_owned(), }) @@ -189,7 +189,7 @@ mod builtin { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::InfiniteSizeCycle { + let expected = Diagnostic::from_error(Error::InfiniteSizeCycle { type_id: "Test::Foo".to_owned(), cycle: "Test::Foo -> Test::Foo".to_owned(), }) @@ -216,7 +216,7 @@ mod builtin { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::InfiniteSizeCycle { + let expected = Diagnostic::from_error(Error::InfiniteSizeCycle { type_id: "Test::Foo".to_owned(), cycle: "Test::Foo -> Test::Foo".to_owned(), }) @@ -245,12 +245,12 @@ mod type_aliases { // Assert let expected = [ - Diagnostic::error(Error::SelfReferentialTypeAliasNeedsConcreteType { + Diagnostic::from_error(Error::SelfReferentialTypeAliasNeedsConcreteType { identifier: "Test::Foo".to_owned(), }) .add_note("failed to resolve type due to a cycle in its definition", None) .add_note("cycle: Test::Foo -> Test::Foo".to_owned(), None), - Diagnostic::error(Error::DoesNotExist { + Diagnostic::from_error(Error::DoesNotExist { identifier: "Test::Foo".to_owned(), }), ]; @@ -273,20 +273,20 @@ mod type_aliases { // Assert let expected = [ - Diagnostic::error(Error::SelfReferentialTypeAliasNeedsConcreteType { + Diagnostic::from_error(Error::SelfReferentialTypeAliasNeedsConcreteType { identifier: "Test::Bar".to_owned(), }) .add_note("failed to resolve type due to a cycle in its definition", None) .add_note("cycle: Test::Bar -> Test::Foo -> Test::Bar".to_owned(), None), - Diagnostic::error(Error::DoesNotExist { + Diagnostic::from_error(Error::DoesNotExist { identifier: "Test::Bar".to_owned(), }), - Diagnostic::error(Error::SelfReferentialTypeAliasNeedsConcreteType { + Diagnostic::from_error(Error::SelfReferentialTypeAliasNeedsConcreteType { identifier: "Test::Foo".to_owned(), }) .add_note("failed to resolve type due to a cycle in its definition", None) .add_note("cycle: Test::Foo -> Test::Bar -> Test::Foo".to_owned(), None), - Diagnostic::error(Error::DoesNotExist { + Diagnostic::from_error(Error::DoesNotExist { identifier: "Test::Foo".to_owned(), }), ]; @@ -308,20 +308,20 @@ mod type_aliases { // Assert: only `Foo` should be marked as cyclic here. let expected = [ - Diagnostic::error(Error::SelfReferentialTypeAliasNeedsConcreteType { + Diagnostic::from_error(Error::SelfReferentialTypeAliasNeedsConcreteType { identifier: "Test::Foo".to_owned(), }) .add_note("failed to resolve type due to a cycle in its definition", None) .add_note("cycle: Test::Foo -> Test::Foo".to_owned(), None), - Diagnostic::error(Error::DoesNotExist { + Diagnostic::from_error(Error::DoesNotExist { identifier: "Test::Foo".to_owned(), }), - Diagnostic::error(Error::SelfReferentialTypeAliasNeedsConcreteType { + Diagnostic::from_error(Error::SelfReferentialTypeAliasNeedsConcreteType { identifier: "Test::Foo".to_owned(), }) .add_note("failed to resolve type due to a cycle in its definition", None) .add_note("cycle: Test::Foo -> Test::Foo".to_owned(), None), - Diagnostic::error(Error::DoesNotExist { + Diagnostic::from_error(Error::DoesNotExist { identifier: "Test::Foo".to_owned(), }), ]; diff --git a/slicec/tests/dictionaries/key_type.rs b/slicec/tests/dictionaries/key_type.rs index b216941f3..9e8e4408f 100644 --- a/slicec/tests/dictionaries/key_type.rs +++ b/slicec/tests/dictionaries/key_type.rs @@ -16,7 +16,7 @@ fn optional_keys_are_disallowed() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::KeyMustBeNonOptional); + let expected = Diagnostic::from_error(Error::KeyMustBeNonOptional); check_diagnostics(diagnostics, [expected]); } @@ -62,7 +62,7 @@ fn disallowed_primitive_types(key_type: &str) { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::KeyTypeNotSupported { kind: key_type.to_owned() }); + let expected = Diagnostic::from_error(Error::KeyTypeNotSupported { kind: key_type.to_owned() }); check_diagnostics(diagnostics, [expected]); } @@ -81,7 +81,7 @@ fn collections_are_disallowed(key_type: &str, key_kind: &str) { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::KeyTypeNotSupported { kind: key_kind.to_owned() }); + let expected = Diagnostic::from_error(Error::KeyTypeNotSupported { kind: key_kind.to_owned() }); check_diagnostics(diagnostics, [expected]); } @@ -119,7 +119,7 @@ fn disallowed_constructed_types(key_type: &str, key_type_def: &str, key_kind: &s let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::KeyTypeNotSupported { + let expected = Diagnostic::from_error(Error::KeyTypeNotSupported { kind: format!("{key_kind} '{key_type}'"), }); check_diagnostics(diagnostics, [expected]); @@ -140,7 +140,7 @@ fn non_compact_structs_are_disallowed() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::StructKeyMustBeCompact); + let expected = Diagnostic::from_error(Error::StructKeyMustBeCompact); check_diagnostics(diagnostics, [expected]); } @@ -190,7 +190,7 @@ fn compact_struct_with_disallowed_fields_is_disallowed() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::StructKeyContainsDisallowedType { + let expected = Diagnostic::from_error(Error::StructKeyContainsDisallowedType { struct_identifier: "Outer".to_owned(), }) .add_note("invalid dictionary key type: sequence", None) diff --git a/slicec/tests/dictionaries/value_type.rs b/slicec/tests/dictionaries/value_type.rs index 2a42b60f3..c98ec08a8 100644 --- a/slicec/tests/dictionaries/value_type.rs +++ b/slicec/tests/dictionaries/value_type.rs @@ -19,10 +19,10 @@ fn invalid_dictionary_values_produce_error() { // Assert let expected = [ - Diagnostic::error(Error::KeyTypeNotSupported { + Diagnostic::from_error(Error::KeyTypeNotSupported { kind: "float32".to_owned(), }), - Diagnostic::error(Error::KeyTypeNotSupported { + Diagnostic::from_error(Error::KeyTypeNotSupported { kind: "float64".to_owned(), }), ]; diff --git a/slicec/tests/enums/container.rs b/slicec/tests/enums/container.rs index c97550451..13678153c 100644 --- a/slicec/tests/enums/container.rs +++ b/slicec/tests/enums/container.rs @@ -22,7 +22,7 @@ fn enumerator_invalid_identifiers(identifier: &str, expected_message: &str) { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Syntax { + let expected = Diagnostic::from_error(Error::Syntax { message: expected_message.to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -64,7 +64,7 @@ mod associated_fields { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::CompactTypeCannotContainTaggedFields { kind: "enum" }) + let expected = Diagnostic::from_error(Error::CompactTypeCannotContainTaggedFields { kind: "enum" }) .add_note("enum 'E' is declared compact here", None); check_diagnostics(diagnostics, [expected]); @@ -125,25 +125,25 @@ mod associated_fields { // Arrange let expected = [ - Diagnostic::error(Error::EnumeratorValueOutOfBounds { + Diagnostic::from_error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "ExplicitNegative".to_owned(), value: -3, min: 0, max: i32::MAX as i128, }), - Diagnostic::error(Error::EnumeratorValueOutOfBounds { + Diagnostic::from_error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "ImplicitNegative".to_owned(), value: -2, min: 0, max: i32::MAX as i128, }), - Diagnostic::error(Error::EnumeratorValueOutOfBounds { + Diagnostic::from_error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "ImplicitOverflow".to_owned(), value: 2_147_483_648, min: 0, max: i32::MAX as i128, }), - Diagnostic::error(Error::EnumeratorValueOutOfBounds { + Diagnostic::from_error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "ExplicitOverflow".to_owned(), value: 0x686921203A7629, min: 0, @@ -241,7 +241,7 @@ mod associated_fields { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::MustContainEnumerators { + let expected = Diagnostic::from_error(Error::MustContainEnumerators { enum_identifier: "E".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -277,7 +277,7 @@ mod associated_fields { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Redefinition { + let expected = Diagnostic::from_error(Error::Redefinition { identifier: "A".to_string(), }) .add_note("'A' was previously defined here", None); @@ -306,7 +306,7 @@ mod underlying_type { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::EnumeratorCannotContainFields { + let expected = Diagnostic::from_error(Error::EnumeratorCannotContainFields { enumerator_identifier: "B".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -372,13 +372,13 @@ mod underlying_type { // Assert let expected = [ - Diagnostic::error(Error::EnumeratorValueOutOfBounds { + Diagnostic::from_error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "B".to_owned(), value: i128::MAX, min: -2147483648, max: 2147483647, }), - Diagnostic::error(Error::EnumeratorValueOutOfBounds { + Diagnostic::from_error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "C".to_owned(), value: i128::MIN, min: -2147483648, @@ -420,7 +420,7 @@ mod underlying_type { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::EnumeratorValueOutOfBounds { + let expected = Diagnostic::from_error(Error::EnumeratorValueOutOfBounds { enumerator_identifier: "A".to_owned(), value: out_of_bounds_value, min: -32768_i128, @@ -464,7 +464,7 @@ mod underlying_type { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::DuplicateEnumeratorValue { enumerator_value: 1 }) + let expected = Diagnostic::from_error(Error::DuplicateEnumeratorValue { enumerator_value: 1 }) .add_note("the value was previously used by 'A' here:", None); check_diagnostics(diagnostics, [expected]); @@ -505,7 +505,7 @@ mod underlying_type { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::MustContainEnumerators { + let expected = Diagnostic::from_error(Error::MustContainEnumerators { enum_identifier: "E".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -568,7 +568,7 @@ mod underlying_type { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::DuplicateEnumeratorValue { enumerator_value: 79 }); + let expected = Diagnostic::from_error(Error::DuplicateEnumeratorValue { enumerator_value: 79 }); check_diagnostics(diagnostics, [expected]); } @@ -587,7 +587,7 @@ mod underlying_type { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Redefinition { + let expected = Diagnostic::from_error(Error::Redefinition { identifier: "A".to_string(), }) .add_note("'A' was previously defined here", None); diff --git a/slicec/tests/enums/mod.rs b/slicec/tests/enums/mod.rs index 123ae0b84..08959abde 100644 --- a/slicec/tests/enums/mod.rs +++ b/slicec/tests/enums/mod.rs @@ -51,7 +51,7 @@ fn invalid_underlying_type(underlying_type: &str) { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::EnumUnderlyingTypeNotSupported { + let expected = Diagnostic::from_error(Error::EnumUnderlyingTypeNotSupported { enum_identifier: "E".to_owned(), kind: Some(underlying_type.to_owned()), }); @@ -73,7 +73,7 @@ fn optional_underlying_types_fail() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::CannotUseOptionalUnderlyingType { + let expected = Diagnostic::from_error(Error::CannotUseOptionalUnderlyingType { enum_identifier: "E".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -118,7 +118,7 @@ fn compact_enums_cannot_have_underlying_types() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::CannotBeCompact { + let expected = Diagnostic::from_error(Error::CannotBeCompact { kind: "enum", identifier: "E".to_owned(), }) @@ -143,7 +143,7 @@ fn compact_enums_cannot_be_unchecked() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::CannotBeCompact { + let expected = Diagnostic::from_error(Error::CannotBeCompact { kind: "enum", identifier: "E".to_owned(), }) diff --git a/slicec/tests/files/io.rs b/slicec/tests/files/io.rs index 4704dce2f..faad964d5 100644 --- a/slicec/tests/files/io.rs +++ b/slicec/tests/files/io.rs @@ -45,7 +45,7 @@ fn duplicate_source_files_ignored_with_warning() { // Assert assert_eq!(files.len(), 1); - let expected = Diagnostic::lint(Lint::DuplicateFile { + let expected = Diagnostic::from_lint(Lint::DuplicateFile { path: "tests/files/../files/test.slice".to_owned(), }); check_diagnostics(diagnostics.into_inner(), [expected]); @@ -71,7 +71,7 @@ fn duplicate_reference_files_ignored_with_warning() { // Assert assert_eq!(files.len(), 1); - let expected = Diagnostic::lint(Lint::DuplicateFile { + let expected = Diagnostic::from_lint(Lint::DuplicateFile { path: "tests/files/../files/test.slice".to_owned(), }); check_diagnostics(diagnostics.into_inner(), [expected]); diff --git a/slicec/tests/identifier_tests.rs b/slicec/tests/identifier_tests.rs index 5285c51c4..29977d487 100644 --- a/slicec/tests/identifier_tests.rs +++ b/slicec/tests/identifier_tests.rs @@ -53,7 +53,7 @@ fn must_start_with_a_letter() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Syntax { + let expected = Diagnostic::from_error(Error::Syntax { message: "unknown symbol '_'".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -88,7 +88,7 @@ fn must_be_ascii_alphanumeric_characters() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Syntax { + let expected = Diagnostic::from_error(Error::Syntax { message: "unknown symbol 'ð’…‹'".to_owned(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/interfaces/inheritance.rs b/slicec/tests/interfaces/inheritance.rs index 94f62ef6b..70d97b7a4 100644 --- a/slicec/tests/interfaces/inheritance.rs +++ b/slicec/tests/interfaces/inheritance.rs @@ -81,7 +81,7 @@ fn must_inherit_from_interface() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::TypeMismatch { + let expected = Diagnostic::from_error(Error::TypeMismatch { expected: "interface".to_owned(), actual: "struct".to_owned(), is_concrete: true, @@ -108,7 +108,7 @@ fn operation_shadowing_is_disallowed() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Shadows { + let expected = Diagnostic::from_error(Error::Shadows { identifier: "op".to_owned(), }) .add_note("'op' was previously defined here", None); diff --git a/slicec/tests/interfaces/mod.rs b/slicec/tests/interfaces/mod.rs index b3a973a65..5dc374b13 100644 --- a/slicec/tests/interfaces/mod.rs +++ b/slicec/tests/interfaces/mod.rs @@ -81,7 +81,7 @@ fn cannot_redefine_operations() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Redefinition { + let expected = Diagnostic::from_error(Error::Redefinition { identifier: "op".to_owned(), }) .add_note("'op' was previously defined here", None); diff --git a/slicec/tests/interfaces/operations.rs b/slicec/tests/interfaces/operations.rs index 847262ef3..a0722ae99 100644 --- a/slicec/tests/interfaces/operations.rs +++ b/slicec/tests/interfaces/operations.rs @@ -190,7 +190,7 @@ fn cannot_redefine_parameters() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Redefinition { + let expected = Diagnostic::from_error(Error::Redefinition { identifier: "a".to_string(), }) .add_note("'a' was previously defined here", None); @@ -213,7 +213,7 @@ fn cannot_redefine_return_members() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Redefinition { + let expected = Diagnostic::from_error(Error::Redefinition { identifier: "a".to_string(), }) .add_note("'a' was previously defined here", None); @@ -239,7 +239,7 @@ fn return_tuple_must_contain_two_or_more_elements(return_tuple: &str) { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::ReturnTuplesMustContainAtLeastTwoElements); + let expected = Diagnostic::from_error(Error::ReturnTuplesMustContainAtLeastTwoElements); check_diagnostics(diagnostics, [expected]); } @@ -287,10 +287,10 @@ mod streams { // Assert let expected = [ - Diagnostic::error(Error::StreamedMembersMustBeLast { + Diagnostic::from_error(Error::StreamedMembersMustBeLast { parameter_identifier: "s".to_owned(), }), - Diagnostic::error(Error::MultipleStreamedMembers), + Diagnostic::from_error(Error::MultipleStreamedMembers), ]; check_diagnostics(diagnostics, expected); } @@ -310,7 +310,7 @@ mod streams { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::StreamedMembersMustBeLast { + let expected = Diagnostic::from_error(Error::StreamedMembersMustBeLast { parameter_identifier: "s".to_owned(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/module_tests.rs b/slicec/tests/module_tests.rs index 019acdca2..f726a5c73 100644 --- a/slicec/tests/module_tests.rs +++ b/slicec/tests/module_tests.rs @@ -46,7 +46,7 @@ mod module { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Syntax { + let expected = Diagnostic::from_error(Error::Syntax { message: "module declaration is required".to_owned(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/parser_tests.rs b/slicec/tests/parser_tests.rs index 6a81bdf6e..5e1c1f270 100644 --- a/slicec/tests/parser_tests.rs +++ b/slicec/tests/parser_tests.rs @@ -49,7 +49,7 @@ fn string_literals_cannot_contain_newlines() { // Assert let span = Span::new((2, 14).into(), (2, 24).into(), "string-0"); - let expected = Diagnostic::error(Error::Syntax { + let expected = Diagnostic::from_error(Error::Syntax { message: "unterminated string literal".to_owned(), }) .set_span(&span); @@ -112,10 +112,10 @@ fn files_are_parsed_independently() { // Assert let expected_message = "expected one of 'doc comment', 'struct', 'interface', 'enum', 'custom', 'typealias', 'compact', 'unchecked', '[', or '::', but found '-'"; let expected = [ - Diagnostic::error(Error::Syntax { + Diagnostic::from_error(Error::Syntax { message: expected_message.to_owned(), }), - Diagnostic::error(Error::Syntax { + Diagnostic::from_error(Error::Syntax { message: expected_message.to_owned(), }), ]; diff --git a/slicec/tests/preprocessor_tests.rs b/slicec/tests/preprocessor_tests.rs index 271a924ce..25efa5feb 100644 --- a/slicec/tests/preprocessor_tests.rs +++ b/slicec/tests/preprocessor_tests.rs @@ -69,7 +69,7 @@ fn identifiers_must_start_with_a_letter(identifier: &str) { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Syntax { + let expected = Diagnostic::from_error(Error::Syntax { message: format!("unknown symbol '{}'", identifier.chars().next().unwrap()), }); check_diagnostics(diagnostics, [expected]); @@ -357,7 +357,7 @@ fn preprocessor_single_backslash_suggestion() { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Syntax { + let expected = Diagnostic::from_error(Error::Syntax { message: "unknown symbol '/', try using '//' instead".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -381,10 +381,10 @@ fn preprocessor_recovers_at_end_of_line() { // Assert let expected = [ - Diagnostic::error(Error::Syntax { + Diagnostic::from_error(Error::Syntax { message: "expected directive_end, but found 'Identifier(\"Bar\")'".to_owned(), }), - Diagnostic::error(Error::Syntax { + Diagnostic::from_error(Error::Syntax { message: r#"expected one of "&&", "||", or ")", but found 'DirectiveEnd'"#.to_owned(), }), ]; diff --git a/slicec/tests/redefinition_tests.rs b/slicec/tests/redefinition_tests.rs index f2079652c..d18c92afd 100644 --- a/slicec/tests/redefinition_tests.rs +++ b/slicec/tests/redefinition_tests.rs @@ -26,7 +26,7 @@ mod redefinition { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Redefinition { + let expected = Diagnostic::from_error(Error::Redefinition { identifier: "S".to_owned(), }) .set_span(&Span::new((8, 20).into(), (8, 21).into(), "string-0")) @@ -55,7 +55,7 @@ mod redefinition { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Redefinition { + let expected = Diagnostic::from_error(Error::Redefinition { identifier: "A".to_owned(), }) .set_span(&Span::new((6, 20).into(), (6, 21).into(), "string-0")) @@ -87,7 +87,7 @@ mod redefinition { let diagnostics = parse_for_diagnostics(slice); // Assert - let i_error = Diagnostic::error(Error::Redefinition { + let i_error = Diagnostic::from_error(Error::Redefinition { identifier: "i".to_owned(), }) .set_span(&Span::new((6, 17).into(), (6, 18).into(), "string-0")) @@ -96,7 +96,7 @@ mod redefinition { Some(&Span::new((5, 17).into(), (5, 18).into(), "string-0")), ); - let s_error = Diagnostic::error(Error::Redefinition { + let s_error = Diagnostic::from_error(Error::Redefinition { identifier: "A".to_owned(), }) .set_span(&Span::new((9, 23).into(), (9, 24).into(), "string-0")) @@ -137,37 +137,37 @@ mod redefinition { // Assert let expected = [ // The struct fields - Diagnostic::error(Error::Redefinition { + Diagnostic::from_error(Error::Redefinition { identifier: "b".to_owned(), }) .set_span(&Span::new((8, 17).into(), (8, 18).into(), "string-0")), // The interface - Diagnostic::error(Error::Redefinition { + Diagnostic::from_error(Error::Redefinition { identifier: "A".to_owned(), }) .set_span(&Span::new((11, 23).into(), (11, 24).into(), "string-0")), // The operation - Diagnostic::error(Error::Redefinition { + Diagnostic::from_error(Error::Redefinition { identifier: "b".to_owned(), }) .set_span(&Span::new((15, 17).into(), (15, 18).into(), "string-0")), // The parameter - Diagnostic::error(Error::Redefinition { + Diagnostic::from_error(Error::Redefinition { identifier: "b".to_owned(), }) .set_span(&Span::new((12, 28).into(), (12, 29).into(), "string-0")), // The return member - Diagnostic::error(Error::Redefinition { + Diagnostic::from_error(Error::Redefinition { identifier: "b".to_owned(), }) .set_span(&Span::new((12, 50).into(), (12, 51).into(), "string-0")), // The enum - Diagnostic::error(Error::Redefinition { + Diagnostic::from_error(Error::Redefinition { identifier: "A".to_owned(), }) .set_span(&Span::new((18, 18).into(), (18, 19).into(), "string-0")), // The enumerator - Diagnostic::error(Error::Redefinition { + Diagnostic::from_error(Error::Redefinition { identifier: "b".to_owned(), }) .set_span(&Span::new((18, 28).into(), (18, 29).into(), "string-0")), @@ -192,7 +192,7 @@ mod redefinition { let diagnostics = parse_multiple_for_diagnostics(&[slice1, slice2]); // Assert - let expected = Diagnostic::error(Error::Redefinition { + let expected = Diagnostic::from_error(Error::Redefinition { identifier: "Bar".to_owned(), }) .set_span(&Span::new((3, 20).into(), (3, 23).into(), "string-1")) diff --git a/slicec/tests/scope_resolution_tests.rs b/slicec/tests/scope_resolution_tests.rs index 57193fb8b..4f5d21061 100644 --- a/slicec/tests/scope_resolution_tests.rs +++ b/slicec/tests/scope_resolution_tests.rs @@ -178,7 +178,7 @@ mod scope_resolution { let diagnostics = parse_multiple_for_diagnostics(&[slice1, slice2]); // Assert - let expected = Diagnostic::error(Error::TypeMismatch { + let expected = Diagnostic::from_error(Error::TypeMismatch { expected: "type".to_string(), actual: "module".to_string(), is_concrete: false, @@ -201,7 +201,7 @@ mod scope_resolution { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::DoesNotExist { + let expected = Diagnostic::from_error(Error::DoesNotExist { identifier: "Nested::C".to_string(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/sequence_tests.rs b/slicec/tests/sequence_tests.rs index 5e4afacc2..2f739aee1 100644 --- a/slicec/tests/sequence_tests.rs +++ b/slicec/tests/sequence_tests.rs @@ -44,7 +44,7 @@ mod sequences { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::KeyTypeNotSupported { + let expected = Diagnostic::from_error(Error::KeyTypeNotSupported { kind: "float32".to_owned(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/structs/container.rs b/slicec/tests/structs/container.rs index c82eb2c16..384898820 100644 --- a/slicec/tests/structs/container.rs +++ b/slicec/tests/structs/container.rs @@ -78,7 +78,7 @@ mod structs { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Redefinition { + let expected = Diagnostic::from_error(Error::Redefinition { identifier: "a".to_owned(), }) .add_note("'a' was previously defined here", None); @@ -106,7 +106,7 @@ mod compact_structs { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::CompactStructCannotBeEmpty); + let expected = Diagnostic::from_error(Error::CompactStructCannotBeEmpty); check_diagnostics(diagnostics, [expected]); } } diff --git a/slicec/tests/structs/tags.rs b/slicec/tests/structs/tags.rs index 2c7dd6783..62f7d9967 100644 --- a/slicec/tests/structs/tags.rs +++ b/slicec/tests/structs/tags.rs @@ -49,7 +49,7 @@ mod compact_structs { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::CompactTypeCannotContainTaggedFields { kind: "struct" }) + let expected = Diagnostic::from_error(Error::CompactTypeCannotContainTaggedFields { kind: "struct" }) .add_note("struct 'S' is declared compact here", None); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/tag_tests.rs b/slicec/tests/tag_tests.rs index 67ab09455..94d34f237 100644 --- a/slicec/tests/tag_tests.rs +++ b/slicec/tests/tag_tests.rs @@ -25,7 +25,7 @@ mod tags { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::TaggedMemberMustBeOptional { + let expected = Diagnostic::from_error(Error::TaggedMemberMustBeOptional { identifier: "b".to_owned(), }); check_diagnostics(diagnostics, [expected]); @@ -45,7 +45,7 @@ mod tags { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::TaggedMemberMustBeOptional { + let expected = Diagnostic::from_error(Error::TaggedMemberMustBeOptional { identifier: "myParam".to_string(), }); check_diagnostics(diagnostics, [expected]); @@ -100,7 +100,7 @@ mod tags { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::CannotHaveDuplicateTag { + let expected = Diagnostic::from_error(Error::CannotHaveDuplicateTag { identifier: "b".to_owned(), }) .add_note("The tag '1' is already being used by member 'a'", None); @@ -143,7 +143,7 @@ mod tags { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::TagValueOutOfBounds); + let expected = Diagnostic::from_error(Error::TagValueOutOfBounds); check_diagnostics(diagnostics, [expected]); } @@ -161,7 +161,7 @@ mod tags { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::TagValueOutOfBounds); + let expected = Diagnostic::from_error(Error::TagValueOutOfBounds); check_diagnostics(diagnostics, [expected]); } @@ -179,7 +179,7 @@ mod tags { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::Syntax { + let expected = Diagnostic::from_error(Error::Syntax { message: "expected one of 'integer literal' or '-', but found 'test string'".to_owned(), }); check_diagnostics(diagnostics, [expected]); diff --git a/slicec/tests/typealias_tests.rs b/slicec/tests/typealias_tests.rs index f1c795b9a..421721b62 100644 --- a/slicec/tests/typealias_tests.rs +++ b/slicec/tests/typealias_tests.rs @@ -123,7 +123,7 @@ mod typealias { let diagnostics = parse_for_diagnostics(slice); // Assert - let expected = Diagnostic::error(Error::TypeAliasOfOptional) + let expected = Diagnostic::from_error(Error::TypeAliasOfOptional) .set_span(&Span::new((3, 13).into(), (3, 27).into(), "string-0")) .add_note( "try removing the trailing `?` modifier from its definition",