mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 11:20:54 +00:00
Merge #11225
11225: internal: Cleanup doc and attribute handling r=Veykril a=Veykril (very vague PR title but as I tried to fix the mentioned issue I ran into more and more subtle things that were interwoven) Fixes https://github.com/rust-analyzer/rust-analyzer/issues/11215 Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
commit
b70493d095
@ -649,8 +649,12 @@ impl Module {
|
||||
let node = ast_id.to_node(db.upcast());
|
||||
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
|
||||
}
|
||||
MacroCallKind::Derive { ast_id, .. }
|
||||
| MacroCallKind::Attr { ast_id, .. } => {
|
||||
MacroCallKind::Derive { ast_id, .. } => {
|
||||
// FIXME: point to the attribute instead, this creates very large diagnostics
|
||||
let node = ast_id.to_node(db.upcast());
|
||||
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
|
||||
}
|
||||
MacroCallKind::Attr { ast_id, .. } => {
|
||||
// FIXME: point to the attribute instead, this creates very large diagnostics
|
||||
let node = ast_id.to_node(db.upcast());
|
||||
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
|
||||
|
@ -18,7 +18,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use syntax::{
|
||||
algo::skip_trivia_token,
|
||||
ast::{self, HasAttrs, HasGenericParams, HasLoopBody},
|
||||
ast::{self, HasAttrs as _, HasGenericParams, HasLoopBody},
|
||||
match_ast, AstNode, AstToken, Direction, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken,
|
||||
TextSize, T,
|
||||
};
|
||||
@ -27,9 +27,9 @@ use crate::{
|
||||
db::HirDatabase,
|
||||
semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
|
||||
source_analyzer::{resolve_hir_path, SourceAnalyzer},
|
||||
Access, AssocItem, BuiltinAttr, Callable, ConstParam, Crate, Field, Function, HasSource,
|
||||
HirFileId, Impl, InFile, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, Name, Path,
|
||||
ScopeDef, ToolModule, Trait, Type, TypeAlias, TypeParam, VariantDef,
|
||||
Access, AssocItem, BuiltinAttr, Callable, ConstParam, Crate, Field, Function, HasAttrs as _,
|
||||
HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef,
|
||||
Name, Path, ScopeDef, ToolModule, Trait, Type, TypeAlias, TypeParam, VariantDef,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@ -486,7 +486,7 @@ impl<'db> SemanticsImpl<'db> {
|
||||
let adt = InFile::new(file_id, &adt);
|
||||
let src = InFile::new(file_id, attr.clone());
|
||||
self.with_ctx(|ctx| {
|
||||
let res = ctx.attr_to_derive_macro_call(adt, src)?;
|
||||
let (_, res) = ctx.attr_to_derive_macro_call(adt, src)?;
|
||||
Some(res.to_vec())
|
||||
})
|
||||
}
|
||||
@ -917,15 +917,14 @@ impl<'db> SemanticsImpl<'db> {
|
||||
let tt = derive.token_tree()?;
|
||||
let file = self.find_file(derive.syntax());
|
||||
let adt = derive.syntax().parent().and_then(ast::Adt::cast)?;
|
||||
|
||||
let adt_def = ToDef::to_def(self, file.with_value(adt.clone()))?;
|
||||
let res = self.with_ctx(|ctx| {
|
||||
let attr_def = ctx.attr_to_def(file.with_value(derive.clone()))?;
|
||||
let derives = ctx.attr_to_derive_macro_call(
|
||||
let (attr_id, derives) = ctx.attr_to_derive_macro_call(
|
||||
file.with_value(&adt),
|
||||
file.with_value(derive.clone()),
|
||||
)?;
|
||||
|
||||
let mut derive_paths = attr_def.parse_path_comma_token_tree()?;
|
||||
let attrs = adt_def.attrs(self.db);
|
||||
let mut derive_paths = attrs[attr_id].parse_path_comma_token_tree()?;
|
||||
|
||||
let derive_idx = tt
|
||||
.syntax()
|
||||
@ -1225,7 +1224,6 @@ to_def_impls![
|
||||
(crate::Local, ast::SelfParam, self_param_to_def),
|
||||
(crate::Label, ast::Label, label_to_def),
|
||||
(crate::Adt, ast::Adt, adt_to_def),
|
||||
(crate::Attr, ast::Attr, attr_to_def),
|
||||
];
|
||||
|
||||
fn find_root(node: &SyntaxNode) -> SyntaxNode {
|
||||
|
@ -87,6 +87,7 @@
|
||||
|
||||
use base_db::FileId;
|
||||
use hir_def::{
|
||||
attr::AttrId,
|
||||
child_by_source::ChildBySource,
|
||||
dyn_map::DynMap,
|
||||
expr::{LabelId, PatId},
|
||||
@ -210,19 +211,6 @@ impl SourceToDefCtx<'_, '_> {
|
||||
ast::Adt::Union(it) => self.union_to_def(InFile::new(file_id, it)).map(AdtId::UnionId),
|
||||
}
|
||||
}
|
||||
pub(super) fn attr_to_def(
|
||||
&mut self,
|
||||
InFile { file_id, value }: InFile<ast::Attr>,
|
||||
) -> Option<crate::Attr> {
|
||||
// FIXME: Use dynmap?
|
||||
let adt = value.syntax().parent().and_then(ast::Adt::cast)?;
|
||||
let attr_pos = ast::HasAttrs::attrs(&adt).position(|it| it == value)?;
|
||||
let attrs = {
|
||||
let def = self.adt_to_def(InFile::new(file_id, adt))?;
|
||||
self.db.attrs(def.into())
|
||||
};
|
||||
attrs.get(attr_pos).cloned()
|
||||
}
|
||||
pub(super) fn bind_pat_to_def(
|
||||
&mut self,
|
||||
src: InFile<ast::IdentPat>,
|
||||
@ -254,16 +242,16 @@ impl SourceToDefCtx<'_, '_> {
|
||||
|
||||
pub(super) fn item_to_macro_call(&mut self, src: InFile<ast::Item>) -> Option<MacroCallId> {
|
||||
let map = self.dyn_map(src.as_ref())?;
|
||||
map[keys::ATTR_MACRO].get(&src).copied()
|
||||
map[keys::ATTR_MACRO_CALL].get(&src).copied()
|
||||
}
|
||||
|
||||
pub(super) fn attr_to_derive_macro_call(
|
||||
&mut self,
|
||||
item: InFile<&ast::Adt>,
|
||||
src: InFile<ast::Attr>,
|
||||
) -> Option<&[Option<MacroCallId>]> {
|
||||
) -> Option<(AttrId, &[Option<MacroCallId>])> {
|
||||
let map = self.dyn_map(item)?;
|
||||
map[keys::DERIVE_MACRO].get(&src).map(AsRef::as_ref)
|
||||
map[keys::DERIVE_MACRO_CALL].get(&src).map(|(id, ids)| (*id, &**ids))
|
||||
}
|
||||
|
||||
fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>(
|
||||
@ -328,7 +316,8 @@ impl SourceToDefCtx<'_, '_> {
|
||||
}
|
||||
|
||||
pub(super) fn macro_to_def(&mut self, src: InFile<ast::Macro>) -> Option<MacroDefId> {
|
||||
let makro = self.dyn_map(src.as_ref()).and_then(|it| it[keys::MACRO].get(&src).copied());
|
||||
let makro =
|
||||
self.dyn_map(src.as_ref()).and_then(|it| it[keys::MACRO_CALL].get(&src).copied());
|
||||
if let res @ Some(_) = makro {
|
||||
return res;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use std::{fmt, hash::Hash, ops, sync::Arc};
|
||||
use base_db::CrateId;
|
||||
use cfg::{CfgExpr, CfgOptions};
|
||||
use either::Either;
|
||||
use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile};
|
||||
use hir_expand::{hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile};
|
||||
use itertools::Itertools;
|
||||
use la_arena::ArenaMap;
|
||||
use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
|
||||
@ -84,6 +84,14 @@ impl ops::Deref for Attrs {
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<AttrId> for Attrs {
|
||||
type Output = Attr;
|
||||
|
||||
fn index(&self, AttrId { ast_index, .. }: AttrId) -> &Self::Output {
|
||||
&(**self)[ast_index as usize]
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Deref for AttrsWithOwner {
|
||||
type Target = Attrs;
|
||||
|
||||
@ -509,23 +517,23 @@ fn inner_attributes(
|
||||
) -> Option<(impl Iterator<Item = ast::Attr>, impl Iterator<Item = ast::Comment>)> {
|
||||
let (attrs, docs) = match_ast! {
|
||||
match syntax {
|
||||
ast::SourceFile(it) => (it.attrs(), ast::CommentIter::from_syntax_node(it.syntax())),
|
||||
ast::SourceFile(it) => (it.attrs(), ast::DocCommentIter::from_syntax_node(it.syntax())),
|
||||
ast::ExternBlock(it) => {
|
||||
let extern_item_list = it.extern_item_list()?;
|
||||
(extern_item_list.attrs(), ast::CommentIter::from_syntax_node(extern_item_list.syntax()))
|
||||
(extern_item_list.attrs(), ast::DocCommentIter::from_syntax_node(extern_item_list.syntax()))
|
||||
},
|
||||
ast::Fn(it) => {
|
||||
let body = it.body()?;
|
||||
let stmt_list = body.stmt_list()?;
|
||||
(stmt_list.attrs(), ast::CommentIter::from_syntax_node(body.syntax()))
|
||||
(stmt_list.attrs(), ast::DocCommentIter::from_syntax_node(body.syntax()))
|
||||
},
|
||||
ast::Impl(it) => {
|
||||
let assoc_item_list = it.assoc_item_list()?;
|
||||
(assoc_item_list.attrs(), ast::CommentIter::from_syntax_node(assoc_item_list.syntax()))
|
||||
(assoc_item_list.attrs(), ast::DocCommentIter::from_syntax_node(assoc_item_list.syntax()))
|
||||
},
|
||||
ast::Module(it) => {
|
||||
let item_list = it.item_list()?;
|
||||
(item_list.attrs(), ast::CommentIter::from_syntax_node(item_list.syntax()))
|
||||
(item_list.attrs(), ast::DocCommentIter::from_syntax_node(item_list.syntax()))
|
||||
},
|
||||
// FIXME: BlockExpr's only accept inner attributes in specific cases
|
||||
// Excerpt from the reference:
|
||||
@ -542,27 +550,20 @@ fn inner_attributes(
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AttrSourceMap {
|
||||
attrs: Vec<InFile<ast::Attr>>,
|
||||
doc_comments: Vec<InFile<ast::Comment>>,
|
||||
source: Vec<Either<ast::Attr, ast::Comment>>,
|
||||
file_id: HirFileId,
|
||||
}
|
||||
|
||||
impl AttrSourceMap {
|
||||
fn new(owner: InFile<&dyn ast::HasAttrs>) -> Self {
|
||||
let mut attrs = Vec::new();
|
||||
let mut doc_comments = Vec::new();
|
||||
for (_, attr) in collect_attrs(owner.value) {
|
||||
match attr {
|
||||
Either::Left(attr) => attrs.push(owner.with_value(attr)),
|
||||
Either::Right(comment) => doc_comments.push(owner.with_value(comment)),
|
||||
}
|
||||
Self {
|
||||
source: collect_attrs(owner.value).map(|(_, it)| it).collect(),
|
||||
file_id: owner.file_id,
|
||||
}
|
||||
|
||||
Self { attrs, doc_comments }
|
||||
}
|
||||
|
||||
fn merge(&mut self, other: Self) {
|
||||
self.attrs.extend(other.attrs);
|
||||
self.doc_comments.extend(other.doc_comments);
|
||||
self.source.extend(other.source);
|
||||
}
|
||||
|
||||
/// Maps the lowered `Attr` back to its original syntax node.
|
||||
@ -571,24 +572,15 @@ impl AttrSourceMap {
|
||||
///
|
||||
/// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of
|
||||
/// the attribute represented by `Attr`.
|
||||
pub fn source_of(&self, attr: &Attr) -> InFile<Either<ast::Attr, ast::Comment>> {
|
||||
pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> {
|
||||
self.source_of_id(attr.id)
|
||||
}
|
||||
|
||||
fn source_of_id(&self, id: AttrId) -> InFile<Either<ast::Attr, ast::Comment>> {
|
||||
if id.is_doc_comment {
|
||||
self.doc_comments
|
||||
.get(id.ast_index as usize)
|
||||
.unwrap_or_else(|| panic!("cannot find doc comment at index {:?}", id))
|
||||
.clone()
|
||||
.map(Either::Right)
|
||||
} else {
|
||||
self.attrs
|
||||
.get(id.ast_index as usize)
|
||||
.unwrap_or_else(|| panic!("cannot find `Attr` at index {:?}", id))
|
||||
.clone()
|
||||
.map(Either::Left)
|
||||
}
|
||||
fn source_of_id(&self, id: AttrId) -> InFile<&Either<ast::Attr, ast::Comment>> {
|
||||
self.source
|
||||
.get(id.ast_index as usize)
|
||||
.map(|it| InFile::new(self.file_id, it))
|
||||
.unwrap_or_else(|| panic!("cannot find attr at index {:?}", id))
|
||||
}
|
||||
}
|
||||
|
||||
@ -656,8 +648,7 @@ fn get_doc_string_in_attr(it: &ast::Attr) -> Option<ast::String> {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub(crate) struct AttrId {
|
||||
is_doc_comment: bool,
|
||||
pub struct AttrId {
|
||||
pub(crate) ast_index: u32,
|
||||
}
|
||||
|
||||
@ -816,27 +807,20 @@ fn collect_attrs(
|
||||
.map_or((None, None), |(attrs, docs)| (Some(attrs), Some(docs)));
|
||||
|
||||
let outer_attrs = owner.attrs().filter(|attr| attr.kind().is_outer());
|
||||
let attrs =
|
||||
outer_attrs.chain(inner_attrs.into_iter().flatten()).enumerate().map(|(idx, attr)| {
|
||||
(
|
||||
AttrId { ast_index: idx as u32, is_doc_comment: false },
|
||||
attr.syntax().text_range().start(),
|
||||
Either::Left(attr),
|
||||
)
|
||||
});
|
||||
let attrs = outer_attrs
|
||||
.chain(inner_attrs.into_iter().flatten())
|
||||
.map(|attr| (attr.syntax().text_range().start(), Either::Left(attr)));
|
||||
|
||||
let outer_docs =
|
||||
ast::CommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer);
|
||||
let docs =
|
||||
outer_docs.chain(inner_docs.into_iter().flatten()).enumerate().map(|(idx, docs_text)| {
|
||||
(
|
||||
AttrId { ast_index: idx as u32, is_doc_comment: true },
|
||||
docs_text.syntax().text_range().start(),
|
||||
Either::Right(docs_text),
|
||||
)
|
||||
});
|
||||
ast::DocCommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer);
|
||||
let docs = outer_docs
|
||||
.chain(inner_docs.into_iter().flatten())
|
||||
.map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text)));
|
||||
// sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
|
||||
docs.chain(attrs).sorted_by_key(|&(_, offset, _)| offset).map(|(id, _, attr)| (id, attr))
|
||||
docs.chain(attrs)
|
||||
.sorted_by_key(|&(offset, _)| offset)
|
||||
.enumerate()
|
||||
.map(|(id, (_, attr))| (AttrId { ast_index: id as u32 }, attr))
|
||||
}
|
||||
|
||||
pub(crate) fn variants_attrs_source_map(
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
use either::Either;
|
||||
use hir_expand::HirFileId;
|
||||
use syntax::ast::HasAttrs;
|
||||
use syntax::ast::HasDocComments;
|
||||
|
||||
use crate::{
|
||||
db::DefDatabase,
|
||||
@ -110,7 +110,7 @@ impl ChildBySource for ItemScope {
|
||||
// FIXME: Do we need to add proc-macros into a PROCMACRO dynmap here?
|
||||
Either::Right(_fn) => return,
|
||||
};
|
||||
res[keys::MACRO].insert(src, makro);
|
||||
res[keys::MACRO_CALL].insert(src, makro);
|
||||
}
|
||||
});
|
||||
self.unnamed_consts().for_each(|konst| {
|
||||
@ -120,13 +120,16 @@ impl ChildBySource for ItemScope {
|
||||
self.impls().for_each(|imp| add_impl(db, file_id, res, imp));
|
||||
self.attr_macro_invocs().for_each(|(ast_id, call_id)| {
|
||||
let item = ast_id.with_value(ast_id.to_node(db.upcast()));
|
||||
res[keys::ATTR_MACRO].insert(item, call_id);
|
||||
res[keys::ATTR_MACRO_CALL].insert(item, call_id);
|
||||
});
|
||||
self.derive_macro_invocs().for_each(|(ast_id, calls)| {
|
||||
let item = ast_id.to_node(db.upcast());
|
||||
let adt = ast_id.to_node(db.upcast());
|
||||
for (attr_id, calls) in calls {
|
||||
if let Some(attr) = item.attrs().nth(attr_id.ast_index as usize) {
|
||||
res[keys::DERIVE_MACRO].insert(ast_id.with_value(attr), calls.into());
|
||||
if let Some(Either::Right(attr)) =
|
||||
adt.doc_comments_and_attrs().nth(attr_id.ast_index as usize)
|
||||
{
|
||||
res[keys::DERIVE_MACRO_CALL]
|
||||
.insert(ast_id.with_value(attr), (attr_id, calls.into()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -67,7 +67,7 @@ pub struct ItemScope {
|
||||
/// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
|
||||
/// paired with the derive macro invocations for the specific attribute.
|
||||
derive_macros:
|
||||
FxHashMap<AstId<ast::Item>, SmallVec<[(AttrId, SmallVec<[Option<MacroCallId>; 1]>); 1]>>,
|
||||
FxHashMap<AstId<ast::Adt>, SmallVec<[(AttrId, SmallVec<[Option<MacroCallId>; 1]>); 1]>>,
|
||||
}
|
||||
|
||||
pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
|
||||
@ -204,12 +204,12 @@ impl ItemScope {
|
||||
|
||||
pub(crate) fn set_derive_macro_invoc(
|
||||
&mut self,
|
||||
item: AstId<ast::Item>,
|
||||
adt: AstId<ast::Adt>,
|
||||
call: MacroCallId,
|
||||
attr_id: AttrId,
|
||||
idx: usize,
|
||||
) {
|
||||
if let Some(derives) = self.derive_macros.get_mut(&item) {
|
||||
if let Some(derives) = self.derive_macros.get_mut(&adt) {
|
||||
if let Some((_, invocs)) = derives.iter_mut().find(|&&mut (id, _)| id == attr_id) {
|
||||
invocs[idx] = Some(call);
|
||||
}
|
||||
@ -221,17 +221,17 @@ impl ItemScope {
|
||||
/// independent of their indices.
|
||||
pub(crate) fn init_derive_attribute(
|
||||
&mut self,
|
||||
item: AstId<ast::Item>,
|
||||
adt: AstId<ast::Adt>,
|
||||
attr_id: AttrId,
|
||||
len: usize,
|
||||
) {
|
||||
self.derive_macros.entry(item).or_default().push((attr_id, smallvec![None; len]));
|
||||
self.derive_macros.entry(adt).or_default().push((attr_id, smallvec![None; len]));
|
||||
}
|
||||
|
||||
pub(crate) fn derive_macro_invocs(
|
||||
&self,
|
||||
) -> impl Iterator<
|
||||
Item = (AstId<ast::Item>, impl Iterator<Item = (AttrId, &[Option<MacroCallId>])>),
|
||||
Item = (AstId<ast::Adt>, impl Iterator<Item = (AttrId, &[Option<MacroCallId>])>),
|
||||
> + '_ {
|
||||
self.derive_macros
|
||||
.iter()
|
||||
|
@ -30,9 +30,9 @@ use crate::{A, B};
|
||||
use a::{c, d::{e}};
|
||||
"#,
|
||||
expect![[r##"
|
||||
#![doc = " file comment"] // AttrId { is_doc_comment: true, ast_index: 0 }
|
||||
#![no_std] // AttrId { is_doc_comment: false, ast_index: 0 }
|
||||
#![doc = " another file comment"] // AttrId { is_doc_comment: true, ast_index: 1 }
|
||||
#![doc = " file comment"] // AttrId { ast_index: 0 }
|
||||
#![no_std] // AttrId { ast_index: 1 }
|
||||
#![doc = " another file comment"] // AttrId { ast_index: 2 }
|
||||
|
||||
pub(self) extern crate self as renamed;
|
||||
|
||||
@ -42,7 +42,7 @@ use a::{c, d::{e}};
|
||||
|
||||
pub(self) use globs::*;
|
||||
|
||||
#[doc = " docs on import"] // AttrId { is_doc_comment: true, ast_index: 0 }
|
||||
#[doc = " docs on import"] // AttrId { ast_index: 0 }
|
||||
pub(self) use crate::{A, B};
|
||||
|
||||
pub(self) use a::{c, d::{e}};
|
||||
@ -67,15 +67,15 @@ extern "C" {
|
||||
}
|
||||
"#,
|
||||
expect![[r##"
|
||||
#[on_extern_block] // AttrId { is_doc_comment: false, ast_index: 0 }
|
||||
#[on_extern_block] // AttrId { ast_index: 0 }
|
||||
extern "C" {
|
||||
#[on_extern_type] // AttrId { is_doc_comment: false, ast_index: 0 }
|
||||
#[on_extern_type] // AttrId { ast_index: 0 }
|
||||
pub(self) type ExType;
|
||||
|
||||
#[on_extern_static] // AttrId { is_doc_comment: false, ast_index: 0 }
|
||||
#[on_extern_static] // AttrId { ast_index: 0 }
|
||||
pub(self) static EX_STATIC: u8 = _;
|
||||
|
||||
#[on_extern_fn] // AttrId { is_doc_comment: false, ast_index: 0 }
|
||||
#[on_extern_fn] // AttrId { ast_index: 0 }
|
||||
// flags = 0x20
|
||||
pub(self) fn ex_fn() -> ();
|
||||
}
|
||||
@ -116,14 +116,14 @@ enum E {
|
||||
expect![[r##"
|
||||
pub(self) struct Unit;
|
||||
|
||||
#[derive(Debug)] // AttrId { is_doc_comment: false, ast_index: 0 }
|
||||
#[derive(Debug)] // AttrId { ast_index: 0 }
|
||||
pub(self) struct Struct {
|
||||
#[doc = " fld docs"] // AttrId { is_doc_comment: true, ast_index: 0 }
|
||||
#[doc = " fld docs"] // AttrId { ast_index: 0 }
|
||||
pub(self) fld: (),
|
||||
}
|
||||
|
||||
pub(self) struct Tuple(
|
||||
#[attr] // AttrId { is_doc_comment: false, ast_index: 0 }
|
||||
#[attr] // AttrId { ast_index: 0 }
|
||||
pub(self) 0: u8,
|
||||
);
|
||||
|
||||
@ -133,14 +133,14 @@ enum E {
|
||||
}
|
||||
|
||||
pub(self) enum E {
|
||||
#[doc = " comment on Unit"] // AttrId { is_doc_comment: true, ast_index: 0 }
|
||||
#[doc = " comment on Unit"] // AttrId { ast_index: 0 }
|
||||
Unit,
|
||||
#[doc = " comment on Tuple"] // AttrId { is_doc_comment: true, ast_index: 0 }
|
||||
#[doc = " comment on Tuple"] // AttrId { ast_index: 0 }
|
||||
Tuple(
|
||||
pub(self) 0: u8,
|
||||
),
|
||||
Struct {
|
||||
#[doc = " comment on a: u8"] // AttrId { is_doc_comment: true, ast_index: 0 }
|
||||
#[doc = " comment on a: u8"] // AttrId { ast_index: 0 }
|
||||
pub(self) a: u8,
|
||||
},
|
||||
}
|
||||
@ -171,11 +171,11 @@ trait Tr: SuperTrait + 'lifetime {
|
||||
|
||||
pub(self) const _: Anon = _;
|
||||
|
||||
#[attr] // AttrId { is_doc_comment: false, ast_index: 0 }
|
||||
#[inner_attr_in_fn] // AttrId { is_doc_comment: false, ast_index: 1 }
|
||||
#[attr] // AttrId { ast_index: 0 }
|
||||
#[inner_attr_in_fn] // AttrId { ast_index: 1 }
|
||||
// flags = 0x2
|
||||
pub(self) fn f(
|
||||
#[attr] // AttrId { is_doc_comment: false, ast_index: 0 }
|
||||
#[attr] // AttrId { ast_index: 0 }
|
||||
arg: u8,
|
||||
_: (),
|
||||
) -> ();
|
||||
@ -212,8 +212,8 @@ mod inline {
|
||||
mod outline;
|
||||
"#,
|
||||
expect![[r##"
|
||||
#[doc = " outer"] // AttrId { is_doc_comment: true, ast_index: 0 }
|
||||
#[doc = " inner"] // AttrId { is_doc_comment: true, ast_index: 1 }
|
||||
#[doc = " outer"] // AttrId { ast_index: 0 }
|
||||
#[doc = " inner"] // AttrId { ast_index: 1 }
|
||||
pub(self) mod inline {
|
||||
pub(self) use super::*;
|
||||
|
||||
|
@ -7,6 +7,7 @@ use rustc_hash::FxHashMap;
|
||||
use syntax::{ast, AstNode, AstPtr};
|
||||
|
||||
use crate::{
|
||||
attr::AttrId,
|
||||
dyn_map::{DynMap, Policy},
|
||||
ConstId, ConstParamId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId,
|
||||
StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
|
||||
@ -31,9 +32,9 @@ pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
|
||||
pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
|
||||
pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new();
|
||||
|
||||
pub const MACRO: Key<ast::Macro, MacroDefId> = Key::new();
|
||||
pub const ATTR_MACRO: Key<ast::Item, MacroCallId> = Key::new();
|
||||
pub const DERIVE_MACRO: Key<ast::Attr, Box<[Option<MacroCallId>]>> = Key::new();
|
||||
pub const MACRO_CALL: Key<ast::Macro, MacroDefId> = Key::new();
|
||||
pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new();
|
||||
pub const DERIVE_MACRO_CALL: Key<ast::Attr, (AttrId, Box<[Option<MacroCallId>]>)> = Key::new();
|
||||
|
||||
/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
|
||||
/// equal if they point to exactly the same object.
|
||||
|
@ -751,7 +751,7 @@ fn macro_call_as_call_id(
|
||||
}
|
||||
|
||||
fn derive_macro_as_call_id(
|
||||
item_attr: &AstIdWithPath<ast::Item>,
|
||||
item_attr: &AstIdWithPath<ast::Adt>,
|
||||
derive_attr: AttrId,
|
||||
db: &dyn db::DefDatabase,
|
||||
krate: CrateId,
|
||||
|
@ -8,6 +8,7 @@ use std::iter;
|
||||
use base_db::{CrateId, Edition, FileId, ProcMacroId};
|
||||
use cfg::{CfgExpr, CfgOptions};
|
||||
use hir_expand::{
|
||||
ast_id_map::FileAstId,
|
||||
builtin_attr_macro::find_builtin_attr,
|
||||
builtin_derive_macro::find_builtin_derive,
|
||||
builtin_fn_macro::find_builtin_macro,
|
||||
@ -30,8 +31,8 @@ use crate::{
|
||||
intern::Interned,
|
||||
item_scope::{ImportType, PerNsGlobImports},
|
||||
item_tree::{
|
||||
self, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, MacroCall, MacroDef,
|
||||
MacroRules, Mod, ModItem, ModKind, TreeId,
|
||||
self, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall,
|
||||
MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
|
||||
},
|
||||
macro_call_as_call_id,
|
||||
nameres::{
|
||||
@ -217,7 +218,7 @@ struct MacroDirective {
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
enum MacroDirectiveKind {
|
||||
FnLike { ast_id: AstIdWithPath<ast::MacroCall>, expand_to: ExpandTo },
|
||||
Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId, derive_pos: usize },
|
||||
Derive { ast_id: AstIdWithPath<ast::Adt>, derive_attr: AttrId, derive_pos: usize },
|
||||
Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem, tree: TreeId },
|
||||
}
|
||||
|
||||
@ -1129,8 +1130,11 @@ impl DefCollector<'_> {
|
||||
) {
|
||||
// Resolved to `#[derive]`
|
||||
|
||||
match mod_item {
|
||||
ModItem::Struct(_) | ModItem::Union(_) | ModItem::Enum(_) => (),
|
||||
let item_tree = tree.item_tree(self.db);
|
||||
let ast_adt_id: FileAstId<ast::Adt> = match *mod_item {
|
||||
ModItem::Struct(strukt) => item_tree[strukt].ast_id().upcast(),
|
||||
ModItem::Union(union) => item_tree[union].ast_id().upcast(),
|
||||
ModItem::Enum(enum_) => item_tree[enum_].ast_id().upcast(),
|
||||
_ => {
|
||||
let diag = DefDiagnostic::invalid_derive_target(
|
||||
directive.module_id,
|
||||
@ -1140,7 +1144,8 @@ impl DefCollector<'_> {
|
||||
self.def_map.diagnostics.push(diag);
|
||||
return recollect_without(self);
|
||||
}
|
||||
}
|
||||
};
|
||||
let ast_id = ast_id.with_value(ast_adt_id);
|
||||
|
||||
match attr.parse_path_comma_token_tree() {
|
||||
Some(derive_macros) => {
|
||||
@ -1274,7 +1279,7 @@ impl DefCollector<'_> {
|
||||
if let Some(def) = def_map.exported_proc_macros.get(&loc.def) {
|
||||
if let ProcMacroKind::CustomDerive { helpers } = &def.kind {
|
||||
self.derive_helpers_in_scope
|
||||
.entry(*ast_id)
|
||||
.entry(ast_id.map(|it| it.upcast()))
|
||||
.or_default()
|
||||
.extend(helpers.iter().cloned());
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ pub enum DefDiagnosticKind {
|
||||
|
||||
InvalidDeriveTarget { ast: AstId<ast::Item>, id: u32 },
|
||||
|
||||
MalformedDerive { ast: AstId<ast::Item>, id: u32 },
|
||||
MalformedDerive { ast: AstId<ast::Adt>, id: u32 },
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
@ -121,7 +121,7 @@ impl DefDiagnostic {
|
||||
|
||||
pub(super) fn malformed_derive(
|
||||
container: LocalModuleId,
|
||||
ast: AstId<ast::Item>,
|
||||
ast: AstId<ast::Adt>,
|
||||
id: AttrId,
|
||||
) -> Self {
|
||||
Self {
|
||||
|
@ -121,7 +121,7 @@ pub enum MacroCallKind {
|
||||
expand_to: ExpandTo,
|
||||
},
|
||||
Derive {
|
||||
ast_id: AstId<ast::Item>,
|
||||
ast_id: AstId<ast::Adt>,
|
||||
derive_name: Box<str>,
|
||||
/// Syntactical index of the invoking `#[derive]` attribute.
|
||||
///
|
||||
@ -328,11 +328,10 @@ impl MacroDefId {
|
||||
impl MacroCallKind {
|
||||
/// Returns the file containing the macro invocation.
|
||||
fn file_id(&self) -> HirFileId {
|
||||
match self {
|
||||
MacroCallKind::FnLike { ast_id, .. } => ast_id.file_id,
|
||||
MacroCallKind::Derive { ast_id, .. } | MacroCallKind::Attr { ast_id, .. } => {
|
||||
ast_id.file_id
|
||||
}
|
||||
match *self {
|
||||
MacroCallKind::FnLike { ast_id: InFile { file_id, .. }, .. }
|
||||
| MacroCallKind::Derive { ast_id: InFile { file_id, .. }, .. }
|
||||
| MacroCallKind::Attr { ast_id: InFile { file_id, .. }, .. } => file_id,
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,7 +340,10 @@ impl MacroCallKind {
|
||||
MacroCallKind::FnLike { ast_id, .. } => {
|
||||
ast_id.with_value(ast_id.to_node(db).syntax().clone())
|
||||
}
|
||||
MacroCallKind::Derive { ast_id, .. } | MacroCallKind::Attr { ast_id, .. } => {
|
||||
MacroCallKind::Derive { ast_id, .. } => {
|
||||
ast_id.with_value(ast_id.to_node(db).syntax().clone())
|
||||
}
|
||||
MacroCallKind::Attr { ast_id, .. } => {
|
||||
ast_id.with_value(ast_id.to_node(db).syntax().clone())
|
||||
}
|
||||
}
|
||||
@ -352,9 +354,8 @@ impl MacroCallKind {
|
||||
MacroCallKind::FnLike { ast_id, .. } => {
|
||||
Some(ast_id.to_node(db).token_tree()?.syntax().clone())
|
||||
}
|
||||
MacroCallKind::Derive { ast_id, .. } | MacroCallKind::Attr { ast_id, .. } => {
|
||||
Some(ast_id.to_node(db).syntax().clone())
|
||||
}
|
||||
MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()),
|
||||
MacroCallKind::Attr { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
.numeric_literal { color: #BFEBBF; }
|
||||
.bool_literal { color: #BFE6EB; }
|
||||
.macro { color: #94BFF3; }
|
||||
.derive { color: #94BFF3; font-style: italic; }
|
||||
.module { color: #AFD8AF; }
|
||||
.value_param { color: #DCDCCC; }
|
||||
.variable { color: #DCDCCC; }
|
||||
|
@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
.numeric_literal { color: #BFEBBF; }
|
||||
.bool_literal { color: #BFE6EB; }
|
||||
.macro { color: #94BFF3; }
|
||||
.derive { color: #94BFF3; font-style: italic; }
|
||||
.module { color: #AFD8AF; }
|
||||
.value_param { color: #DCDCCC; }
|
||||
.variable { color: #DCDCCC; }
|
||||
|
@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
.numeric_literal { color: #BFEBBF; }
|
||||
.bool_literal { color: #BFE6EB; }
|
||||
.macro { color: #94BFF3; }
|
||||
.derive { color: #94BFF3; font-style: italic; }
|
||||
.module { color: #AFD8AF; }
|
||||
.value_param { color: #DCDCCC; }
|
||||
.variable { color: #DCDCCC; }
|
||||
|
@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
.numeric_literal { color: #BFEBBF; }
|
||||
.bool_literal { color: #BFE6EB; }
|
||||
.macro { color: #94BFF3; }
|
||||
.derive { color: #94BFF3; font-style: italic; }
|
||||
.module { color: #AFD8AF; }
|
||||
.value_param { color: #DCDCCC; }
|
||||
.variable { color: #DCDCCC; }
|
||||
|
@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
.numeric_literal { color: #BFEBBF; }
|
||||
.bool_literal { color: #BFE6EB; }
|
||||
.macro { color: #94BFF3; }
|
||||
.derive { color: #94BFF3; font-style: italic; }
|
||||
.module { color: #AFD8AF; }
|
||||
.value_param { color: #DCDCCC; }
|
||||
.variable { color: #DCDCCC; }
|
||||
|
@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
.numeric_literal { color: #BFEBBF; }
|
||||
.bool_literal { color: #BFE6EB; }
|
||||
.macro { color: #94BFF3; }
|
||||
.derive { color: #94BFF3; font-style: italic; }
|
||||
.module { color: #AFD8AF; }
|
||||
.value_param { color: #DCDCCC; }
|
||||
.variable { color: #DCDCCC; }
|
||||
|
@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
.numeric_literal { color: #BFEBBF; }
|
||||
.bool_literal { color: #BFE6EB; }
|
||||
.macro { color: #94BFF3; }
|
||||
.derive { color: #94BFF3; font-style: italic; }
|
||||
.module { color: #AFD8AF; }
|
||||
.value_param { color: #DCDCCC; }
|
||||
.variable { color: #DCDCCC; }
|
||||
|
@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
.numeric_literal { color: #BFEBBF; }
|
||||
.bool_literal { color: #BFE6EB; }
|
||||
.macro { color: #94BFF3; }
|
||||
.derive { color: #94BFF3; font-style: italic; }
|
||||
.module { color: #AFD8AF; }
|
||||
.value_param { color: #DCDCCC; }
|
||||
.variable { color: #DCDCCC; }
|
||||
|
@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
.numeric_literal { color: #BFEBBF; }
|
||||
.bool_literal { color: #BFE6EB; }
|
||||
.macro { color: #94BFF3; }
|
||||
.derive { color: #94BFF3; font-style: italic; }
|
||||
.module { color: #AFD8AF; }
|
||||
.value_param { color: #DCDCCC; }
|
||||
.variable { color: #DCDCCC; }
|
||||
|
@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
.numeric_literal { color: #BFEBBF; }
|
||||
.bool_literal { color: #BFE6EB; }
|
||||
.macro { color: #94BFF3; }
|
||||
.derive { color: #94BFF3; font-style: italic; }
|
||||
.module { color: #AFD8AF; }
|
||||
.value_param { color: #DCDCCC; }
|
||||
.variable { color: #DCDCCC; }
|
||||
@ -89,7 +90,17 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
<span class="brace">}</span>
|
||||
|
||||
<span class="keyword">use</span> <span class="self_keyword crate_root">self</span><span class="operator">::</span><span class="struct">FooCopy</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="struct declaration">BarCopy</span><span class="brace">}</span><span class="semicolon">;</span>
|
||||
|
||||
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
|
||||
<span class="comment documentation">/// This is a doc comment</span>
|
||||
<span class="comment">// This is a normal comment</span>
|
||||
<span class="comment documentation">/// This is a doc comment</span>
|
||||
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
|
||||
<span class="comment">// This is another normal comment</span>
|
||||
<span class="comment documentation">/// This is another doc comment</span>
|
||||
<span class="comment">// This is another normal comment</span>
|
||||
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
|
||||
<span class="comment">// The reason for these being here is to test AttrIds</span>
|
||||
<span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="brace">{</span>
|
||||
<span class="field declaration">x</span><span class="colon">:</span> <span class="builtin_type">u32</span><span class="comma">,</span>
|
||||
<span class="brace">}</span>
|
||||
|
@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
.numeric_literal { color: #BFEBBF; }
|
||||
.bool_literal { color: #BFE6EB; }
|
||||
.macro { color: #94BFF3; }
|
||||
.derive { color: #94BFF3; font-style: italic; }
|
||||
.module { color: #AFD8AF; }
|
||||
.value_param { color: #DCDCCC; }
|
||||
.variable { color: #DCDCCC; }
|
||||
|
@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
.numeric_literal { color: #BFEBBF; }
|
||||
.bool_literal { color: #BFE6EB; }
|
||||
.macro { color: #94BFF3; }
|
||||
.derive { color: #94BFF3; font-style: italic; }
|
||||
.module { color: #AFD8AF; }
|
||||
.value_param { color: #DCDCCC; }
|
||||
.variable { color: #DCDCCC; }
|
||||
|
@ -62,7 +62,17 @@ impl Foo {
|
||||
}
|
||||
|
||||
use self::FooCopy::{self as BarCopy};
|
||||
|
||||
#[derive(Copy)]
|
||||
/// This is a doc comment
|
||||
// This is a normal comment
|
||||
/// This is a doc comment
|
||||
#[derive(Copy)]
|
||||
// This is another normal comment
|
||||
/// This is another doc comment
|
||||
// This is another normal comment
|
||||
#[derive(Copy)]
|
||||
// The reason for these being here is to test AttrIds
|
||||
struct FooCopy {
|
||||
x: u32,
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ jemalloc-ctl = { version = "0.4.1", package = "tikv-jemalloc-ctl", optional = tr
|
||||
perf-event = "0.4"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3.8", features = ["psapi"] }
|
||||
winapi = { version = "0.3.8", features = ["processthreadsapi", "psapi"] }
|
||||
|
||||
[features]
|
||||
cpu_profiler = []
|
||||
|
@ -17,7 +17,7 @@ always-assert = { version = "0.1.2", features = ["log"] }
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
miow = "0.4.0"
|
||||
winapi = "0.3.9"
|
||||
winapi = { version = "0.3.9", features = ["winerror"] }
|
||||
|
||||
[features]
|
||||
# Uncomment to enable for the whole crate graph
|
||||
|
@ -30,7 +30,7 @@ pub use self::{
|
||||
QuoteOffsets, Radix,
|
||||
},
|
||||
traits::{
|
||||
CommentIter, HasArgList, HasAttrs, HasDocComments, HasGenericParams, HasLoopBody,
|
||||
DocCommentIter, HasArgList, HasAttrs, HasDocComments, HasGenericParams, HasLoopBody,
|
||||
HasModuleItem, HasName, HasTypeBounds, HasVisibility,
|
||||
},
|
||||
};
|
||||
|
@ -216,6 +216,7 @@ pub struct SourceFile {
|
||||
}
|
||||
impl ast::HasAttrs for SourceFile {}
|
||||
impl ast::HasModuleItem for SourceFile {}
|
||||
impl ast::HasDocComments for SourceFile {}
|
||||
impl SourceFile {
|
||||
pub fn shebang_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![shebang]) }
|
||||
}
|
||||
@ -227,6 +228,7 @@ pub struct Const {
|
||||
impl ast::HasAttrs for Const {}
|
||||
impl ast::HasName for Const {}
|
||||
impl ast::HasVisibility for Const {}
|
||||
impl ast::HasDocComments for Const {}
|
||||
impl Const {
|
||||
pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
|
||||
pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
|
||||
@ -246,6 +248,7 @@ impl ast::HasAttrs for Enum {}
|
||||
impl ast::HasName for Enum {}
|
||||
impl ast::HasVisibility for Enum {}
|
||||
impl ast::HasGenericParams for Enum {}
|
||||
impl ast::HasDocComments for Enum {}
|
||||
impl Enum {
|
||||
pub fn enum_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![enum]) }
|
||||
pub fn variant_list(&self) -> Option<VariantList> { support::child(&self.syntax) }
|
||||
@ -283,6 +286,7 @@ impl ast::HasAttrs for Fn {}
|
||||
impl ast::HasName for Fn {}
|
||||
impl ast::HasVisibility for Fn {}
|
||||
impl ast::HasGenericParams for Fn {}
|
||||
impl ast::HasDocComments for Fn {}
|
||||
impl Fn {
|
||||
pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
|
||||
pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
|
||||
@ -303,6 +307,7 @@ pub struct Impl {
|
||||
impl ast::HasAttrs for Impl {}
|
||||
impl ast::HasVisibility for Impl {}
|
||||
impl ast::HasGenericParams for Impl {}
|
||||
impl ast::HasDocComments for Impl {}
|
||||
impl Impl {
|
||||
pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
|
||||
pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
|
||||
@ -320,6 +325,7 @@ pub struct MacroRules {
|
||||
impl ast::HasAttrs for MacroRules {}
|
||||
impl ast::HasName for MacroRules {}
|
||||
impl ast::HasVisibility for MacroRules {}
|
||||
impl ast::HasDocComments for MacroRules {}
|
||||
impl MacroRules {
|
||||
pub fn macro_rules_token(&self) -> Option<SyntaxToken> {
|
||||
support::token(&self.syntax, T![macro_rules])
|
||||
@ -335,6 +341,7 @@ pub struct MacroDef {
|
||||
impl ast::HasAttrs for MacroDef {}
|
||||
impl ast::HasName for MacroDef {}
|
||||
impl ast::HasVisibility for MacroDef {}
|
||||
impl ast::HasDocComments for MacroDef {}
|
||||
impl MacroDef {
|
||||
pub fn macro_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![macro]) }
|
||||
pub fn args(&self) -> Option<TokenTree> { support::child(&self.syntax) }
|
||||
@ -348,6 +355,7 @@ pub struct Module {
|
||||
impl ast::HasAttrs for Module {}
|
||||
impl ast::HasName for Module {}
|
||||
impl ast::HasVisibility for Module {}
|
||||
impl ast::HasDocComments for Module {}
|
||||
impl Module {
|
||||
pub fn mod_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mod]) }
|
||||
pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) }
|
||||
@ -361,6 +369,7 @@ pub struct Static {
|
||||
impl ast::HasAttrs for Static {}
|
||||
impl ast::HasName for Static {}
|
||||
impl ast::HasVisibility for Static {}
|
||||
impl ast::HasDocComments for Static {}
|
||||
impl Static {
|
||||
pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
|
||||
pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
|
||||
@ -379,6 +388,7 @@ impl ast::HasAttrs for Struct {}
|
||||
impl ast::HasName for Struct {}
|
||||
impl ast::HasVisibility for Struct {}
|
||||
impl ast::HasGenericParams for Struct {}
|
||||
impl ast::HasDocComments for Struct {}
|
||||
impl Struct {
|
||||
pub fn struct_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![struct]) }
|
||||
pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
|
||||
@ -394,6 +404,7 @@ impl ast::HasName for Trait {}
|
||||
impl ast::HasVisibility for Trait {}
|
||||
impl ast::HasGenericParams for Trait {}
|
||||
impl ast::HasTypeBounds for Trait {}
|
||||
impl ast::HasDocComments for Trait {}
|
||||
impl Trait {
|
||||
pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
|
||||
pub fn auto_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![auto]) }
|
||||
@ -410,6 +421,7 @@ impl ast::HasName for TypeAlias {}
|
||||
impl ast::HasVisibility for TypeAlias {}
|
||||
impl ast::HasGenericParams for TypeAlias {}
|
||||
impl ast::HasTypeBounds for TypeAlias {}
|
||||
impl ast::HasDocComments for TypeAlias {}
|
||||
impl TypeAlias {
|
||||
pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
|
||||
pub fn type_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![type]) }
|
||||
@ -426,6 +438,7 @@ impl ast::HasAttrs for Union {}
|
||||
impl ast::HasName for Union {}
|
||||
impl ast::HasVisibility for Union {}
|
||||
impl ast::HasGenericParams for Union {}
|
||||
impl ast::HasDocComments for Union {}
|
||||
impl Union {
|
||||
pub fn union_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![union]) }
|
||||
pub fn record_field_list(&self) -> Option<RecordFieldList> { support::child(&self.syntax) }
|
||||
@ -437,6 +450,7 @@ pub struct Use {
|
||||
}
|
||||
impl ast::HasAttrs for Use {}
|
||||
impl ast::HasVisibility for Use {}
|
||||
impl ast::HasDocComments for Use {}
|
||||
impl Use {
|
||||
pub fn use_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![use]) }
|
||||
pub fn use_tree(&self) -> Option<UseTree> { support::child(&self.syntax) }
|
||||
@ -582,6 +596,7 @@ pub struct RecordField {
|
||||
impl ast::HasAttrs for RecordField {}
|
||||
impl ast::HasName for RecordField {}
|
||||
impl ast::HasVisibility for RecordField {}
|
||||
impl ast::HasDocComments for RecordField {}
|
||||
impl RecordField {
|
||||
pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
|
||||
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
|
||||
@ -593,6 +608,7 @@ pub struct TupleField {
|
||||
}
|
||||
impl ast::HasAttrs for TupleField {}
|
||||
impl ast::HasVisibility for TupleField {}
|
||||
impl ast::HasDocComments for TupleField {}
|
||||
impl TupleField {
|
||||
pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
|
||||
}
|
||||
@ -614,6 +630,7 @@ pub struct Variant {
|
||||
impl ast::HasAttrs for Variant {}
|
||||
impl ast::HasName for Variant {}
|
||||
impl ast::HasVisibility for Variant {}
|
||||
impl ast::HasDocComments for Variant {}
|
||||
impl Variant {
|
||||
pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) }
|
||||
pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
|
||||
@ -1567,6 +1584,7 @@ pub enum Adt {
|
||||
Union(Union),
|
||||
}
|
||||
impl ast::HasAttrs for Adt {}
|
||||
impl ast::HasDocComments for Adt {}
|
||||
impl ast::HasGenericParams for Adt {}
|
||||
impl ast::HasName for Adt {}
|
||||
impl ast::HasVisibility for Adt {}
|
||||
@ -1609,6 +1627,12 @@ pub struct AnyHasAttrs {
|
||||
}
|
||||
impl ast::HasAttrs for AnyHasAttrs {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct AnyHasDocComments {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
impl ast::HasDocComments for AnyHasDocComments {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct AnyHasGenericParams {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
@ -3869,6 +3893,27 @@ impl AstNode for AnyHasAttrs {
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||
}
|
||||
impl AnyHasDocComments {
|
||||
#[inline]
|
||||
pub fn new<T: ast::HasDocComments>(node: T) -> AnyHasDocComments {
|
||||
AnyHasDocComments { syntax: node.syntax().clone() }
|
||||
}
|
||||
}
|
||||
impl AstNode for AnyHasDocComments {
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
match kind {
|
||||
SOURCE_FILE | CONST | ENUM | FN | IMPL | MACRO_RULES | MACRO_DEF | MODULE | STATIC
|
||||
| STRUCT | TRAIT | TYPE_ALIAS | UNION | USE | RECORD_FIELD | TUPLE_FIELD | VARIANT => {
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||
Self::can_cast(syntax.kind()).then(|| AnyHasDocComments { syntax })
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||
}
|
||||
impl AnyHasGenericParams {
|
||||
#[inline]
|
||||
pub fn new<T: ast::HasGenericParams>(node: T) -> AnyHasGenericParams {
|
||||
|
@ -771,21 +771,14 @@ impl ast::HasLoopBody for ast::ForExpr {
|
||||
}
|
||||
}
|
||||
|
||||
impl ast::HasDocComments for ast::SourceFile {}
|
||||
impl ast::HasDocComments for ast::Fn {}
|
||||
impl ast::HasDocComments for ast::Struct {}
|
||||
impl ast::HasDocComments for ast::Union {}
|
||||
impl ast::HasDocComments for ast::RecordField {}
|
||||
impl ast::HasDocComments for ast::TupleField {}
|
||||
impl ast::HasDocComments for ast::Enum {}
|
||||
impl ast::HasDocComments for ast::Variant {}
|
||||
impl ast::HasDocComments for ast::Trait {}
|
||||
impl ast::HasDocComments for ast::Module {}
|
||||
impl ast::HasDocComments for ast::Static {}
|
||||
impl ast::HasDocComments for ast::Const {}
|
||||
impl ast::HasDocComments for ast::TypeAlias {}
|
||||
impl ast::HasDocComments for ast::Impl {}
|
||||
impl ast::HasDocComments for ast::MacroRules {}
|
||||
impl ast::HasDocComments for ast::MacroDef {}
|
||||
impl ast::HasDocComments for ast::Macro {}
|
||||
impl ast::HasDocComments for ast::Use {}
|
||||
impl ast::HasAttrs for ast::AnyHasDocComments {}
|
||||
|
||||
impl From<ast::Adt> for ast::Item {
|
||||
fn from(it: ast::Adt) -> Self {
|
||||
match it {
|
||||
ast::Adt::Enum(it) => ast::Item::Enum(it),
|
||||
ast::Adt::Struct(it) => ast::Item::Struct(it),
|
||||
ast::Adt::Union(it) => ast::Item::Union(it),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,10 @@ impl ast::Comment {
|
||||
CommentKind::from_text(self.text())
|
||||
}
|
||||
|
||||
pub fn is_doc(&self) -> bool {
|
||||
self.kind().doc.is_some()
|
||||
}
|
||||
|
||||
pub fn is_inner(&self) -> bool {
|
||||
self.kind().doc == Some(CommentPlacement::Inner)
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
//! Various traits that are implemented by ast nodes.
|
||||
//!
|
||||
//! The implementations are usually trivial, and live in generated.rs
|
||||
use itertools::Either;
|
||||
|
||||
use crate::{
|
||||
ast::{self, support, AstChildren, AstNode, AstToken},
|
||||
syntax_node::SyntaxElementChildren,
|
||||
SyntaxToken, T,
|
||||
SyntaxElement, SyntaxToken, T,
|
||||
};
|
||||
|
||||
pub trait HasName: AstNode {
|
||||
@ -71,14 +73,17 @@ pub trait HasAttrs: AstNode {
|
||||
}
|
||||
|
||||
pub trait HasDocComments: HasAttrs {
|
||||
fn doc_comments(&self) -> CommentIter {
|
||||
CommentIter { iter: self.syntax().children_with_tokens() }
|
||||
fn doc_comments(&self) -> DocCommentIter {
|
||||
DocCommentIter { iter: self.syntax().children_with_tokens() }
|
||||
}
|
||||
fn doc_comments_and_attrs(&self) -> AttrCommentIter {
|
||||
AttrCommentIter { iter: self.syntax().children_with_tokens() }
|
||||
}
|
||||
}
|
||||
|
||||
impl CommentIter {
|
||||
pub fn from_syntax_node(syntax_node: &ast::SyntaxNode) -> CommentIter {
|
||||
CommentIter { iter: syntax_node.children_with_tokens() }
|
||||
impl DocCommentIter {
|
||||
pub fn from_syntax_node(syntax_node: &ast::SyntaxNode) -> DocCommentIter {
|
||||
DocCommentIter { iter: syntax_node.children_with_tokens() }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -95,13 +100,31 @@ impl CommentIter {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CommentIter {
|
||||
pub struct DocCommentIter {
|
||||
iter: SyntaxElementChildren,
|
||||
}
|
||||
|
||||
impl Iterator for CommentIter {
|
||||
impl Iterator for DocCommentIter {
|
||||
type Item = ast::Comment;
|
||||
fn next(&mut self) -> Option<ast::Comment> {
|
||||
self.iter.by_ref().find_map(|el| el.into_token().and_then(ast::Comment::cast))
|
||||
self.iter.by_ref().find_map(|el| {
|
||||
el.into_token().and_then(ast::Comment::cast).filter(ast::Comment::is_doc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AttrCommentIter {
|
||||
iter: SyntaxElementChildren,
|
||||
}
|
||||
|
||||
impl Iterator for AttrCommentIter {
|
||||
type Item = Either<ast::Comment, ast::Attr>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.by_ref().find_map(|el| match el {
|
||||
SyntaxElement::Node(node) => ast::Attr::cast(node).map(Either::Right),
|
||||
SyntaxElement::Token(tok) => {
|
||||
ast::Comment::cast(tok).filter(ast::Comment::is_doc).map(Either::Left)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -777,6 +777,33 @@ fn extract_struct_traits(ast: &mut AstSrc) {
|
||||
extract_struct_trait(node, name, methods);
|
||||
}
|
||||
}
|
||||
|
||||
let nodes_with_doc_comments = [
|
||||
"SourceFile",
|
||||
"Fn",
|
||||
"Struct",
|
||||
"Union",
|
||||
"RecordField",
|
||||
"TupleField",
|
||||
"Enum",
|
||||
"Variant",
|
||||
"Trait",
|
||||
"Module",
|
||||
"Static",
|
||||
"Const",
|
||||
"TypeAlias",
|
||||
"Impl",
|
||||
"MacroRules",
|
||||
"MacroDef",
|
||||
"Macro",
|
||||
"Use",
|
||||
];
|
||||
|
||||
for node in &mut ast.nodes {
|
||||
if nodes_with_doc_comments.contains(&&*node.name) {
|
||||
node.traits.push("HasDocComments".into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_struct_trait(node: &mut AstNodeSrc, trait_name: &str, methods: &[&str]) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user