Skip to content

Commit

Permalink
Add support for custom tags
Browse files Browse the repository at this point in the history
Fixes hyperledger-solang#1524

Signed-off-by: Sean Young <sean@mess.org>
  • Loading branch information
seanyoung committed Sep 14, 2023
1 parent f43c319 commit c159019
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 17 deletions.
52 changes: 35 additions & 17 deletions src/sema/tags.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// SPDX-License-Identifier: Apache-2.0

use super::ast::{Diagnostic, Namespace, Parameter, Tag};
use solang_parser::{doccomment::DocComment, pt};
use solang_parser::{
doccomment::{DocComment, DocCommentTag},
pt,
};
use std::fmt::Write;

/// Resolve the tags for a type from parsed doccomment
Expand All @@ -23,18 +26,7 @@ pub fn resolve_tags(

match c.tag.as_str() {
"notice" | "author" | "title" | "dev" => {
// fold fields with the same name
if let Some(prev) = res.iter_mut().find(|e| e.tag == c.tag) {
prev.value.push(' ');
prev.value.push_str(&c.value);
} else {
res.push(Tag {
loc,
tag: c.tag.to_owned(),
value: c.value.to_owned(),
no: 0,
})
}
fold_tag(loc, &mut res, c);
}
"param" if params.is_some() => {
let v: Vec<&str> = c.value.splitn(2, char::is_whitespace).collect();
Expand Down Expand Up @@ -167,17 +159,43 @@ pub fn resolve_tags(
}
}
_ => {
ns.diagnostics.push(Diagnostic::error(
tag_loc,
format!("tag '@{}' is not valid for {}", c.tag, ty),
));
if let Some(custom) = c.tag.strip_prefix("custom:") {
if custom.is_empty() {
ns.diagnostics.push(Diagnostic::error(
tag_loc,
format!("custom tag '@{}' is missing a name", c.tag),
));
} else {
fold_tag(loc, &mut res, c);
}
} else {
ns.diagnostics.push(Diagnostic::error(
tag_loc,
format!("tag '@{}' is not valid for {}", c.tag, ty),
));
}
}
}
}

res
}

fn fold_tag(loc: pt::Loc, res: &mut Vec<Tag>, doc_comment: &DocCommentTag) {
// fold fields with the same name
if let Some(prev) = res.iter_mut().find(|e| e.tag == doc_comment.tag) {
prev.value.push(' ');
prev.value.push_str(&doc_comment.value);
} else {
res.push(Tag {
loc,
tag: doc_comment.tag.to_owned(),
value: doc_comment.value.to_owned(),
no: 0,
})
}
}

/// Render tags as plain text string
pub fn render(tags: &[Tag]) -> String {
let mut s = String::new();
Expand Down
11 changes: 11 additions & 0 deletions tests/solana_tests/tags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ fn contract() {
/// @author Mr Foo
/// @dev this is
/// a contract
/// @custom:meh words for
/// @custom:meh custom tag
/// @custom: custom tag
@program_id("Seed23VDZ9HFCfKvFwmemB6dpi25n5XjZdP52B2RUmh")
contract test {
/// @dev construct this
Expand All @@ -24,6 +27,11 @@ fn contract() {
Target::Solana,
);

assert_eq!(
ns.diagnostics.first_error(),
"custom tag '@custom:' is missing a name"
);

assert_eq!(ns.contracts[0].tags[0].tag, "notice");
assert_eq!(ns.contracts[0].tags[0].value, "So Hello, World");

Expand All @@ -36,6 +44,9 @@ fn contract() {
assert_eq!(ns.contracts[0].tags[3].tag, "dev");
assert_eq!(ns.contracts[0].tags[3].value, "this is\na contract");

assert_eq!(ns.contracts[0].tags[4].tag, "custom:meh");
assert_eq!(ns.contracts[0].tags[4].value, "words for custom tag");

let constructor = ns
.functions
.iter()
Expand Down

0 comments on commit c159019

Please sign in to comment.