solar_ast/ast/natspec.rs
1use super::BoxSlice;
2use crate::token::CommentKind;
3use solar_interface::{Ident, Span, Symbol};
4use std::fmt;
5
6/// A single doc-comment: `/// foo`, `/** bar */`.
7#[derive(Debug)]
8pub struct DocComment<'ast> {
9 /// The comment kind.
10 pub kind: CommentKind,
11 /// The comment's span including its "quotes" (`//`, `/**`).
12 pub span: Span,
13 /// The comment's contents excluding its "quotes" (`//`, `/**`)
14 /// similarly to symbols in string literal tokens.
15 pub symbol: Symbol,
16 /// The comment's natspec items
17 pub natspec: BoxSlice<'ast, NatSpecItem>,
18}
19
20impl<'ast> DocComment<'ast> {
21 /// Returns the content of a natspec excluding its tag.
22 pub fn natspec_content<'a>(&self, item: &'a NatSpecItem) -> &'a str {
23 item.content()
24 }
25}
26
27/// A single item within a Natspec comment block.
28#[derive(Clone, Copy, Debug)]
29pub struct NatSpecItem {
30 /// The tag identifier of the item.
31 pub kind: NatSpecKind,
32 /// Span of the tag. '@' is not included.
33 pub span: Span,
34 /// The symbol containing this tag's content.
35 pub symbol: Symbol,
36 /// Byte offset into the doc comment's symbol where this tag's content starts.
37 pub content_start: u32,
38 /// Byte offset into the doc comment's symbol where this tag's content ends.
39 pub content_end: u32,
40}
41
42impl NatSpecItem {
43 /// Returns the byte range of this item's content within the doc comment's symbol.
44 pub fn content_range(&self) -> std::ops::Range<usize> {
45 self.content_start as usize..self.content_end as usize
46 }
47
48 /// Returns the text content of this natspec item.
49 ///
50 /// The content is extracted from the symbol using the byte offsets.
51 pub fn content(&self) -> &str {
52 &self.symbol.as_str()[self.content_range()]
53 }
54}
55
56impl fmt::Display for NatSpecItem {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 let content = self.content();
59 match self.kind {
60 NatSpecKind::Title => write!(f, "@title {content}"),
61 NatSpecKind::Author => write!(f, "@author {content}"),
62 NatSpecKind::Notice => write!(f, "@notice {content}"),
63 NatSpecKind::Dev => write!(f, "@dev {content}"),
64 NatSpecKind::Param { name } => write!(f, "@param {} {content}", name.name),
65 NatSpecKind::Return { name: Some(name) } => {
66 write!(f, "@return {} {content}", name.name)
67 }
68 NatSpecKind::Return { name: None } => write!(f, "@return {content}"),
69 NatSpecKind::Inheritdoc { contract } => {
70 write!(f, "@inheritdoc {} {content}", contract.name)
71 }
72 NatSpecKind::Custom { name } => write!(f, "@custom:{} {content}", name.name),
73 NatSpecKind::Internal { tag } => write!(f, "@{} {content}", tag.name),
74 }
75 }
76}
77
78/// The kind of a [`NatSpecItem`].
79///
80/// Reference: <https://docs.soliditylang.org/en/latest/natspec-format.html#tags>
81#[derive(Clone, Copy, Debug, PartialEq, Eq)]
82pub enum NatSpecKind {
83 /// `@title`
84 ///
85 /// A title that describes the contract.
86 Title,
87 /// `@author`
88 ///
89 /// The name of the author.
90 Author,
91 /// `@notice`
92 ///
93 /// An annotation for end-users.
94 Notice,
95 /// `@dev`
96 ///
97 /// A technical annotation for developers.
98 Dev,
99 /// `@param <name>`
100 ///
101 /// Documents a parameter. The `name` field contains the parameter name.
102 Param { name: Ident },
103 /// `@return <name>`
104 ///
105 /// Documents a return variable. The optional `name` field contains the return variable name.
106 Return { name: Option<Ident> },
107 /// `@inheritdoc <contract>`
108 ///
109 /// Copies all tags from the base function. The `contract` field contains the contract name.
110 Inheritdoc { contract: Ident },
111 /// `@custom:<tag>`
112 ///
113 /// Custom tag with user-defined semantics. The `name` field contains the custom tag name.
114 Custom { name: Ident },
115
116 /// `@<tag>`
117 ///
118 /// Internal tags reserved for compiler purposes. The `tag` field contains the tag name.
119 Internal { tag: Ident },
120}
121
122/// Internal natspec tags.
123pub const NATSPEC_INTERNAL_TAGS: &[&str] = &["solidity", "src", "use-src", "ast-id"];