1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | |
5 | use std::io::Write; |
6 | |
7 | use crate::bindgen::config::{Config, DocumentationLength, DocumentationStyle, Language}; |
8 | use crate::bindgen::utilities::SynAttributeHelpers; |
9 | use crate::bindgen::writer::{Source, SourceWriter}; |
10 | |
11 | #[derive (Debug, Clone)] |
12 | pub struct Documentation { |
13 | pub doc_comment: Vec<String>, |
14 | } |
15 | |
16 | impl Documentation { |
17 | pub fn load(attrs: &[syn::Attribute]) -> Self { |
18 | let doc: Vec = attrsimpl Iterator |
19 | .get_comment_lines() |
20 | .into_iter() |
21 | .filter(|x: &String| !x.trim_start().starts_with("cbindgen:" )) |
22 | .collect(); |
23 | |
24 | Documentation { doc_comment: doc } |
25 | } |
26 | |
27 | pub fn simple(line: &str) -> Self { |
28 | Documentation { |
29 | doc_comment: vec![line.to_owned()], |
30 | } |
31 | } |
32 | |
33 | pub fn none() -> Self { |
34 | Documentation { |
35 | doc_comment: Vec::new(), |
36 | } |
37 | } |
38 | } |
39 | |
40 | impl Source for Documentation { |
41 | fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) { |
42 | if self.doc_comment.is_empty() || !config.documentation { |
43 | return; |
44 | } |
45 | |
46 | let end = match config.documentation_length { |
47 | DocumentationLength::Short => 1, |
48 | DocumentationLength::Full => self.doc_comment.len(), |
49 | }; |
50 | |
51 | // Cython uses Python-style comments, so `documentation_style` is not relevant. |
52 | if config.language == Language::Cython { |
53 | for line in &self.doc_comment[..end] { |
54 | write!(out, "# {}" , line); |
55 | out.new_line(); |
56 | } |
57 | return; |
58 | } |
59 | |
60 | let style = match config.documentation_style { |
61 | DocumentationStyle::Auto if config.language == Language::C => DocumentationStyle::Doxy, |
62 | DocumentationStyle::Auto if config.language == Language::Cxx => DocumentationStyle::Cxx, |
63 | DocumentationStyle::Auto => DocumentationStyle::C, // Fallback if `Language` gets extended. |
64 | other => other, |
65 | }; |
66 | |
67 | // Following these documents for style conventions: |
68 | // https://en.wikibooks.org/wiki/C++_Programming/Code/Style_Conventions/Comments |
69 | // https://www.cs.cmu.edu/~410/doc/doxygen.html |
70 | match style { |
71 | DocumentationStyle::C => { |
72 | out.write("/*" ); |
73 | out.new_line(); |
74 | } |
75 | |
76 | DocumentationStyle::Doxy => { |
77 | out.write("/**" ); |
78 | out.new_line(); |
79 | } |
80 | |
81 | _ => (), |
82 | } |
83 | |
84 | for line in &self.doc_comment[..end] { |
85 | match style { |
86 | DocumentationStyle::C => out.write("" ), |
87 | DocumentationStyle::Doxy => out.write(" *" ), |
88 | DocumentationStyle::C99 => out.write("//" ), |
89 | DocumentationStyle::Cxx => out.write("///" ), |
90 | DocumentationStyle::Auto => unreachable!(), // Auto case should always be covered |
91 | } |
92 | |
93 | write!(out, " {}" , line); |
94 | out.new_line(); |
95 | } |
96 | |
97 | match style { |
98 | DocumentationStyle::C => { |
99 | out.write(" */" ); |
100 | out.new_line(); |
101 | } |
102 | |
103 | DocumentationStyle::Doxy => { |
104 | out.write(" */" ); |
105 | out.new_line(); |
106 | } |
107 | |
108 | _ => (), |
109 | } |
110 | } |
111 | } |
112 | |