clang/
documentation.rs

1// Copyright 2016 Kyle Mayes
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Comments.
16
17#![allow(unused_unsafe)]
18
19use std::fmt;
20use std::mem;
21use std::marker::{PhantomData};
22
23use clang_sys::*;
24
25use utility;
26use super::{TranslationUnit};
27
28//================================================
29// Enums
30//================================================
31
32// CommentChild __________________________________
33
34/// A child component of a comment.
35#[derive(Clone, Debug, PartialEq, Eq)]
36pub enum CommentChild {
37    /// A block command with zero or more arguments and a paragraph as an argument.
38    BlockCommand(BlockCommand),
39    /// An HTML start tag.
40    HtmlStartTag(HtmlStartTag),
41    /// An HTML end tag.
42    HtmlEndTag(String),
43    /// An inline command with word-like arguments.
44    InlineCommand(InlineCommand),
45    /// A paragraph containing inline content.
46    Paragraph(Vec<CommentChild>),
47    /// A `\param` command.
48    ParamCommand(ParamCommand),
49    /// A `\tparam` command.
50    TParamCommand(TParamCommand),
51    /// Plain text.
52    Text(String),
53    /// A verbatim command with a closing command.
54    VerbatimCommand(Vec<String>),
55    /// A verbatim command with a single line and no closing command.
56    VerbatimLineCommand(String),
57}
58
59impl CommentChild {
60    //- Constructors -----------------------------
61
62    fn from_raw(raw: CXComment) -> CommentChild {
63        unsafe {
64            match clang_Comment_getKind(raw) {
65                CXComment_Text =>
66                    CommentChild::Text(utility::to_string(clang_TextComment_getText(raw))),
67                CXComment_InlineCommand =>
68                    CommentChild::InlineCommand(InlineCommand::from_raw(raw)),
69                CXComment_HTMLStartTag => CommentChild::HtmlStartTag(HtmlStartTag::from_raw(raw)),
70                CXComment_HTMLEndTag => {
71                    let name = utility::to_string(clang_HTMLTagComment_getTagName(raw));
72                    CommentChild::HtmlEndTag(name)
73                },
74                CXComment_Paragraph =>
75                    CommentChild::Paragraph(Comment::from_raw(raw).get_children()),
76                CXComment_BlockCommand => CommentChild::BlockCommand(BlockCommand::from_raw(raw)),
77                CXComment_ParamCommand => CommentChild::ParamCommand(ParamCommand::from_raw(raw)),
78                CXComment_TParamCommand =>
79                    CommentChild::TParamCommand(TParamCommand::from_raw(raw)),
80                CXComment_VerbatimBlockCommand => {
81                    let lines = iter!(
82                        clang_Comment_getNumChildren(raw),
83                        clang_Comment_getChild(raw),
84                    ).map(|c| {
85                        utility::to_string(clang_VerbatimBlockLineComment_getText(c))
86                    }).collect();
87                    CommentChild::VerbatimCommand(lines)
88                },
89                CXComment_VerbatimLine => {
90                    let line = utility::to_string(clang_VerbatimLineComment_getText(raw));
91                    CommentChild::VerbatimLineCommand(line)
92                },
93                _ => unreachable!(),
94            }
95        }
96    }
97}
98
99// ParameterDirection ____________________________
100
101/// Indicates the parameter passing direction for a `\param` command.
102#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
103#[repr(C)]
104pub enum ParameterDirection {
105    /// Indicates the parameter is an input parameter.
106    In = 0,
107    /// Indicates the parameter is an output parameter.
108    Out = 1,
109    /// Indicates the parameter is both an input and an output parameter.
110    InOut = 2,
111}
112
113// InlineCommandStyle ____________________________
114
115/// Indicates the appropriate rendering style for an inline command argument.
116#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
117#[repr(C)]
118pub enum InlineCommandStyle {
119    /// Indicates the command should be rendered in a bold font.
120    Bold = 1,
121    /// Indicates the command should be rendered in a monospace font.
122    Monospace = 2,
123    /// Indicates the command should be rendered emphasized (typically italicized).
124    Emphasized = 3,
125}
126
127//================================================
128// Structs
129//================================================
130
131// BlockCommand __________________________________
132
133/// A block command with zero or more arguments and a paragraph as an argument.
134#[derive(Clone, Debug, PartialEq, Eq)]
135pub struct BlockCommand {
136    /// The command.
137    pub command: String,
138    /// The command arguments.
139    pub arguments: Vec<String>,
140    /// The children of the paragraph argument.
141    pub children: Vec<CommentChild>,
142}
143
144impl BlockCommand {
145    //- Constructors -----------------------------
146
147    unsafe fn from_raw(raw: CXComment) -> BlockCommand {
148        let command = utility::to_string(clang_BlockCommandComment_getCommandName(raw));
149        let arguments = iter!(
150            clang_BlockCommandComment_getNumArgs(raw),
151            clang_BlockCommandComment_getArgText(raw),
152        ).map(utility::to_string).collect();
153        let paragraph = clang_BlockCommandComment_getParagraph(raw);
154        let children = Comment::from_raw(paragraph).get_children();
155        BlockCommand { command, arguments, children }
156    }
157}
158
159// Comment _______________________________________
160
161/// A comment attached to a declaration.
162#[derive(Copy, Clone)]
163pub struct Comment<'tu> {
164    raw: CXComment,
165    _marker: PhantomData<&'tu TranslationUnit<'tu>>,
166}
167
168impl<'tu> Comment<'tu> {
169    //- Constructors -----------------------------
170
171    #[doc(hidden)]
172    pub fn from_raw(raw: CXComment) -> Comment<'tu> {
173        Comment { raw, _marker: PhantomData }
174    }
175
176    //- Accessors --------------------------------
177
178    /// Returns the children of this comment.
179    pub fn get_children(&self) -> Vec<CommentChild> {
180        iter!(
181            clang_Comment_getNumChildren(self.raw),
182            clang_Comment_getChild(self.raw),
183        ).map(CommentChild::from_raw).collect()
184    }
185
186    /// Returns this comment as an HTML string.
187    pub fn as_html(&self) -> String {
188        unsafe { utility::to_string(clang_FullComment_getAsHTML(self.raw)) }
189    }
190
191    /// Returns this comment as an XML string.
192    pub fn as_xml(&self) -> String {
193        unsafe { utility::to_string(clang_FullComment_getAsXML(self.raw)) }
194    }
195}
196
197impl<'tu> fmt::Debug for Comment<'tu> {
198    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
199        write!(formatter, "{:?}", self.get_children())
200    }
201}
202
203// HtmlStartTag __________________________________
204
205/// An HTML start tag.
206#[derive(Clone, Debug, PartialEq, Eq)]
207pub struct HtmlStartTag {
208    /// The tag name.
209    pub name: String,
210    /// The attributes associated with the tag, if any.
211    pub attributes: Vec<(String,  String)>,
212    /// Whether the tag is self-closing.
213    pub closing: bool,
214}
215
216impl HtmlStartTag {
217    //- Constructors -----------------------------
218
219    unsafe fn from_raw(raw: CXComment) -> HtmlStartTag {
220        let name = utility::to_string(clang_HTMLTagComment_getTagName(raw));
221        let attributes = iter!(
222            clang_HTMLStartTag_getNumAttrs(raw),
223            clang_HTMLStartTag_getAttrName(raw),
224            clang_HTMLStartTag_getAttrValue(raw),
225        ).map(|(n, v)| (utility::to_string(n), utility::to_string(v))).collect();
226        let closing = clang_HTMLStartTagComment_isSelfClosing(raw) != 0;
227        HtmlStartTag { name, attributes, closing }
228    }
229}
230
231// InlineCommand _________________________________
232
233/// An inline command with word-like arguments.
234#[derive(Clone, Debug, PartialEq, Eq)]
235pub struct InlineCommand {
236    /// The command.
237    pub command: String,
238    /// The command arguments.
239    pub arguments: Vec<String>,
240    /// The style with which to render the command arguments, if any.
241    pub style: Option<InlineCommandStyle>,
242}
243
244impl InlineCommand {
245    //- Constructors -----------------------------
246
247    unsafe fn from_raw(raw: CXComment) -> InlineCommand {
248        let command = utility::to_string(clang_InlineCommandComment_getCommandName(raw));
249        let arguments = iter!(
250            clang_InlineCommandComment_getNumArgs(raw),
251            clang_InlineCommandComment_getArgText(raw),
252        ).map(utility::to_string).collect();
253        let style = match clang_InlineCommandComment_getRenderKind(raw) {
254            CXCommentInlineCommandRenderKind_Normal => None,
255            other => Some(mem::transmute(other)),
256        };
257        InlineCommand { command, arguments, style }
258    }
259}
260
261// ParamCommand __________________________________
262
263/// A `\param` command.
264#[derive(Clone, Debug, PartialEq, Eq)]
265pub struct ParamCommand {
266    /// The index of the parameter, if this command refers to a valid parameter.
267    pub index: Option<usize>,
268    /// The parameter.
269    pub parameter: String,
270    /// The parameter direction, if specified.
271    pub direction: Option<ParameterDirection>,
272    /// The children of this parameter.
273    pub children: Vec<CommentChild>
274}
275
276impl ParamCommand {
277    //- Constructors -----------------------------
278
279    unsafe fn from_raw(raw: CXComment) -> ParamCommand {
280        let index = if clang_ParamCommandComment_isParamIndexValid(raw) != 0 {
281            Some(clang_ParamCommandComment_getParamIndex(raw) as usize)
282        } else {
283            None
284        };
285        let parameter = utility::to_string(clang_ParamCommandComment_getParamName(raw));
286        let direction = if clang_ParamCommandComment_isDirectionExplicit(raw) != 0 {
287            Some(mem::transmute(clang_ParamCommandComment_getDirection(raw)))
288        } else {
289            None
290        };
291        let paragraph = clang_BlockCommandComment_getParagraph(raw);
292        let children = Comment::from_raw(paragraph).get_children();
293        ParamCommand { index, parameter, direction, children }
294    }
295}
296
297// TParamCommand _________________________________
298
299/// A `\tparam` command.
300#[derive(Clone, Debug, PartialEq, Eq)]
301pub struct TParamCommand {
302    /// The nesting depth and the index of the template parameter, if this command refers to a
303    /// valid template parameter.
304    pub position: Option<(usize, usize)>,
305    /// The template parameter.
306    pub parameter: String,
307    /// The children of this type parameter.
308    pub children: Vec<CommentChild>
309}
310
311impl TParamCommand {
312    //- Constructors -----------------------------
313
314    unsafe fn from_raw(raw: CXComment) -> TParamCommand {
315        let position = if clang_TParamCommandComment_isParamPositionValid(raw) != 0 {
316            let depth = clang_TParamCommandComment_getDepth(raw);
317            let index = clang_TParamCommandComment_getIndex(raw, depth) as usize;
318            Some((depth as usize, index))
319        } else {
320            None
321        };
322        let parameter = utility::to_string(clang_TParamCommandComment_getParamName(raw));
323        let paragraph = clang_BlockCommandComment_getParagraph(raw);
324        let children = Comment::from_raw(paragraph).get_children();
325        TParamCommand { position, parameter, children }
326    }
327}