use crate::util::syn_tools::*;
use crate::util::*;
use crate::*;
use iter_seq_ext::prelude::*;
pub(crate) fn is_target(value: &str) -> bool {
if value.contains("/") {
return false;
}
let value = trim_backtick(value);
let tokens = RsTokens::new(value);
IteratorSeqExt::contains(tokens, &target_path())
}
pub(crate) fn replace_text(value: &str) -> String {
if !is_target(value) {
return value.to_string();
}
let pat_path = &target_path();
let alt_path = &self_path();
let old_tokens = RsTokens::new(value);
let new_tokens = IteratorSeqExt::replace(old_tokens, pat_path, alt_path);
new_tokens.map(|x| x.code().to_string()).collect()
}
pub(crate) fn replace_url(value: &str, self_item: Option<&syn::Item>) -> String {
if !is_target(value) {
return value.to_string();
}
let Some(ref api_id) = self_item.and_then(api_id) else {
return value.to_string();
};
let value = trim_backtick(value);
let api_id = &api_id.to_string();
let pat_path = &target_path();
let alt_path = &item_path(api_id);
let old_tokens = RsTokens::new(value);
let new_tokens = IteratorSeqExt::replace(old_tokens, pat_path, alt_path);
new_tokens.map(|x| x.code().to_string()).collect()
}
fn target_path() -> [RsToken<'static>; 4] {
[
RsToken::new("doc_share", rustc_lexer::TokenKind::Ident),
RsToken::new(":", rustc_lexer::TokenKind::Colon),
RsToken::new(":", rustc_lexer::TokenKind::Colon),
RsToken::new("Self", rustc_lexer::TokenKind::Ident),
]
}
fn self_path() -> [RsToken<'static>; 1] {
[RsToken::new("Self", rustc_lexer::TokenKind::Ident)]
}
fn item_path<'a>(item: &'a str) -> [RsToken<'a>; 1] {
[RsToken::new(item, rustc_lexer::TokenKind::Ident)]
}
fn trim_backtick(value: &str) -> &str {
util::trim_circumfix(value, "`")
}
fn api_id(item: &syn::Item) -> Option<syn::Ident> {
match item {
syn::Item::Const(x) => Some(x.ident.clone()),
syn::Item::Enum(x) => Some(x.ident.clone()),
syn::Item::Fn(x) => Some(x.sig.ident.clone()),
syn::Item::Macro(x) => x.ident.clone(),
syn::Item::Mod(x) => Some(x.ident.clone()),
syn::Item::Static(x) => Some(x.ident.clone()),
syn::Item::Struct(x) => Some(x.ident.clone()),
syn::Item::Trait(x) => Some(x.ident.clone()),
syn::Item::Type(x) => Some(x.ident.clone()),
syn::Item::Impl(x) => type_api_id(&x.self_ty),
_ => None,
}
}
fn type_api_id(ty: &syn::Type) -> Option<syn::Ident> {
match ty {
syn::Type::Array(_) => Some(ns::id("array")),
syn::Type::BareFn(_) => Some(ns::id("fn")),
syn::Type::Ptr(_) => Some(ns::id("pointer")),
syn::Type::Reference(_) => Some(ns::id("reference")),
syn::Type::Slice(_) => Some(ns::id("slice")),
syn::Type::Tuple(_) => Some(ns::id("tuple")),
syn::Type::Path(x) => x.path.get_ident().cloned(),
_ => None,
}
}