Есть ли способ "сделать макрос вещи" в атрибуте без процедурного макроса?
В частности, я пытаюсь поместить вывод макроса в комментарий документа. Я был взволнован, что это делает именно то, что я хочу:
/// foo
///
#[doc="bar\n\nbaz"]
///
/// quux
struct Dummy;
Следующим шагом будет замена этой строки моим контентом. По этому я не могу написать #[doc=my_content!()]
и макросы атрибутов являются процедурными, поэтому для этого мне нужен еще один ящик, плюс (я думаю) мой контент может быть сгенерирован без необходимости каких-либо процедурных макрокомпонентов.
Есть ли способ сделать это с "обычными макросами" каким-то образом, или мне не повезло?
1 ответ
Ответ, кажется, нет.
Если посмотреть на грамматику атрибутов, то, кроме скобок, запятых и знаков равенства, атрибуты могут в конечном итоге содержать только литералы. Таким образом, на этом уровне Rust не позволяет больше.
Тем не менее, инвертирование структуры позволяет что-то вроде этого, и doc-comment
клеть делает это для комментариев к документу. Вместо вызова макроса из атрибута используйте макрос для создания атрибута; этот макрос не ограничивается только получением литералов *. Недостатком является то, что элемент, к которому должен применяться атрибут, должен быть частью вызова макроса. Так это
#[doc=my_content!()]
struct Foo;
становится таким:
doc_comment!(
my_content!(),
struct Foo;
);
Определение макроса просто:
#[macro_export]
macro_rules! doc_comment {
($x:expr, $($tt:tt)*) => {
#[doc = $x]
$($tt)*
};
}
(опущена ветвь исходного макроса, которая не является частью основной структуры)
(спасибо Йонасу-Шлевинку за указание на это)
* за исключением этой последней части (получение макрокоманды в атрибут), ответ на связанный вопрос уже делает именно это.