use crate::diagnostics::{Diagnostic, Diagnostics, Lint};
use crate::grammar::*;
use crate::slice_file::Span;
pub fn validate_common_doc_comments(commentable: &dyn Commentable, diagnostics: &mut Diagnostics) {
let Some(comment) = commentable.comment() else { return };
only_operations_have_parameters(comment, commentable, diagnostics);
only_operations_can_return(comment, commentable, diagnostics);
only_operations_can_throw(comment, commentable, diagnostics);
}
fn only_operations_have_parameters(comment: &DocComment, entity: &dyn Commentable, diagnostics: &mut Diagnostics) {
let concrete_entity = entity.concrete_entity();
if !matches!(concrete_entity, Entities::Operation(_) | Entities::Enumerator(_)) {
for param_tag in &comment.params {
report_only_operation_error(param_tag, param_tag.message.span(), entity, diagnostics);
}
}
}
fn only_operations_can_return(comment: &DocComment, entity: &dyn Commentable, diagnostics: &mut Diagnostics) {
if !matches!(entity.concrete_entity(), Entities::Operation(_)) {
for returns_tag in &comment.returns {
report_only_operation_error(returns_tag, returns_tag.message.span(), entity, diagnostics);
}
}
}
fn only_operations_can_throw(comment: &DocComment, entity: &dyn Commentable, diagnostics: &mut Diagnostics) {
if !matches!(entity.concrete_entity(), Entities::Operation(_)) {
for throws_tag in &comment.throws {
report_only_operation_error(throws_tag, throws_tag.message.span(), entity, diagnostics);
}
}
}
fn report_only_operation_error(
tag: &impl Symbol,
message_span: &Span,
entity: &dyn Commentable,
diagnostics: &mut Diagnostics,
) {
let entity_kind = entity.kind();
let note = format!(
"'{identifier}' is {a} {entity_kind}",
identifier = entity.identifier(),
a = crate::utils::string_util::indefinite_article(entity_kind),
);
let tag_kind = tag.kind().split_once(' ').unwrap().0;
let action_phrase = match tag_kind {
"param" => "have parameters",
"returns" => "return",
"throws" => "throw",
_ => unreachable!("'report_only_operation_error' was called with unsupported tag '{tag_kind}'"),
};
Diagnostic::new(Lint::IncorrectDocComment {
message: format!("comment has a '{tag_kind}' tag, but only operations can {action_phrase}"),
})
.set_span(&(tag.span() + message_span))
.set_scope(entity.parser_scoped_identifier())
.add_note(note, Some(entity.span()))
.push_into(diagnostics);
}