#![allow(unused_unsafe)]
use std::fmt;
use std::marker::PhantomData;
use std::mem;
use clang_sys::*;
use super::TranslationUnit;
use utility;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum CommentChild {
BlockCommand(BlockCommand),
HtmlStartTag(HtmlStartTag),
HtmlEndTag(String),
InlineCommand(InlineCommand),
Paragraph(Vec<CommentChild>),
ParamCommand(ParamCommand),
TParamCommand(TParamCommand),
Text(String),
VerbatimCommand(Vec<String>),
VerbatimLineCommand(String),
}
impl CommentChild {
fn from_raw(raw: CXComment) -> CommentChild {
unsafe {
match clang_Comment_getKind(raw) {
CXComment_Text => {
CommentChild::Text(utility::to_string(clang_TextComment_getText(raw)))
}
CXComment_InlineCommand => {
CommentChild::InlineCommand(InlineCommand::from_raw(raw))
}
CXComment_HTMLStartTag => CommentChild::HtmlStartTag(HtmlStartTag::from_raw(raw)),
CXComment_HTMLEndTag => {
let name = utility::to_string(clang_HTMLTagComment_getTagName(raw));
CommentChild::HtmlEndTag(name)
}
CXComment_Paragraph => {
CommentChild::Paragraph(Comment::from_raw(raw).get_children())
}
CXComment_BlockCommand => CommentChild::BlockCommand(BlockCommand::from_raw(raw)),
CXComment_ParamCommand => CommentChild::ParamCommand(ParamCommand::from_raw(raw)),
CXComment_TParamCommand => {
CommentChild::TParamCommand(TParamCommand::from_raw(raw))
}
CXComment_VerbatimBlockCommand => {
let lines = iter!(
clang_Comment_getNumChildren(raw),
clang_Comment_getChild(raw),
)
.map(|c| utility::to_string(clang_VerbatimBlockLineComment_getText(c)))
.collect();
CommentChild::VerbatimCommand(lines)
}
CXComment_VerbatimLine => {
let line = utility::to_string(clang_VerbatimLineComment_getText(raw));
CommentChild::VerbatimLineCommand(line)
}
_ => unreachable!(),
}
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum ParameterDirection {
In = 0,
Out = 1,
InOut = 2,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(C)]
pub enum InlineCommandStyle {
Bold = 1,
Monospace = 2,
Emphasized = 3,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BlockCommand {
pub command: String,
pub arguments: Vec<String>,
pub children: Vec<CommentChild>,
}
impl BlockCommand {
unsafe fn from_raw(raw: CXComment) -> BlockCommand {
let command = utility::to_string(clang_BlockCommandComment_getCommandName(raw));
let arguments = iter!(
clang_BlockCommandComment_getNumArgs(raw),
clang_BlockCommandComment_getArgText(raw),
)
.map(|cxs| unsafe { utility::to_string(cxs) })
.collect();
let paragraph = clang_BlockCommandComment_getParagraph(raw);
let children = Comment::from_raw(paragraph).get_children();
BlockCommand {
command,
arguments,
children,
}
}
}
#[derive(Copy, Clone)]
pub struct Comment<'tu> {
raw: CXComment,
_marker: PhantomData<&'tu TranslationUnit<'tu>>,
}
impl<'tu> Comment<'tu> {
#[doc(hidden)]
pub fn from_raw(raw: CXComment) -> Comment<'tu> {
Comment {
raw,
_marker: PhantomData,
}
}
pub fn get_children(&self) -> Vec<CommentChild> {
iter!(
clang_Comment_getNumChildren(self.raw),
clang_Comment_getChild(self.raw),
)
.map(CommentChild::from_raw)
.collect()
}
pub fn as_html(&self) -> String {
unsafe { utility::to_string(clang_FullComment_getAsHTML(self.raw)) }
}
pub fn as_xml(&self) -> String {
unsafe { utility::to_string(clang_FullComment_getAsXML(self.raw)) }
}
}
impl<'tu> fmt::Debug for Comment<'tu> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "{:?}", self.get_children())
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct HtmlStartTag {
pub name: String,
pub attributes: Vec<(String, String)>,
pub closing: bool,
}
impl HtmlStartTag {
unsafe fn from_raw(raw: CXComment) -> HtmlStartTag {
let name = utility::to_string(clang_HTMLTagComment_getTagName(raw));
let attributes = iter!(
clang_HTMLStartTag_getNumAttrs(raw),
clang_HTMLStartTag_getAttrName(raw),
clang_HTMLStartTag_getAttrValue(raw),
)
.map(|(n, v)| (utility::to_string(n), utility::to_string(v)))
.collect();
let closing = clang_HTMLStartTagComment_isSelfClosing(raw) != 0;
HtmlStartTag {
name,
attributes,
closing,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct InlineCommand {
pub command: String,
pub arguments: Vec<String>,
pub style: Option<InlineCommandStyle>,
}
impl InlineCommand {
unsafe fn from_raw(raw: CXComment) -> InlineCommand {
let command = utility::to_string(clang_InlineCommandComment_getCommandName(raw));
let arguments = iter!(
clang_InlineCommandComment_getNumArgs(raw),
clang_InlineCommandComment_getArgText(raw),
)
.map(|cxs| unsafe { utility::to_string(cxs) })
.collect();
let style = match clang_InlineCommandComment_getRenderKind(raw) {
CXCommentInlineCommandRenderKind_Normal => None,
other => Some(mem::transmute(other)),
};
InlineCommand {
command,
arguments,
style,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ParamCommand {
pub index: Option<usize>,
pub parameter: String,
pub direction: Option<ParameterDirection>,
pub children: Vec<CommentChild>,
}
impl ParamCommand {
unsafe fn from_raw(raw: CXComment) -> ParamCommand {
let index = if clang_ParamCommandComment_isParamIndexValid(raw) != 0 {
Some(clang_ParamCommandComment_getParamIndex(raw) as usize)
} else {
None
};
let parameter = utility::to_string(clang_ParamCommandComment_getParamName(raw));
let direction = if clang_ParamCommandComment_isDirectionExplicit(raw) != 0 {
Some(mem::transmute(clang_ParamCommandComment_getDirection(raw)))
} else {
None
};
let paragraph = clang_BlockCommandComment_getParagraph(raw);
let children = Comment::from_raw(paragraph).get_children();
ParamCommand {
index,
parameter,
direction,
children,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TParamCommand {
pub position: Option<(usize, usize)>,
pub parameter: String,
pub children: Vec<CommentChild>,
}
impl TParamCommand {
unsafe fn from_raw(raw: CXComment) -> TParamCommand {
let position = if clang_TParamCommandComment_isParamPositionValid(raw) != 0 {
let depth = clang_TParamCommandComment_getDepth(raw);
let index = clang_TParamCommandComment_getIndex(raw, depth) as usize;
Some((depth as usize, index))
} else {
None
};
let parameter = utility::to_string(clang_TParamCommandComment_getParamName(raw));
let paragraph = clang_BlockCommandComment_getParagraph(raw);
let children = Comment::from_raw(paragraph).get_children();
TParamCommand {
position,
parameter,
children,
}
}
}