Skip to content

Commit 9a62d94

Browse files
committed
allow for hackily specifying external libraries that should be documented
1 parent f085efa commit 9a62d94

File tree

5 files changed

+87
-32
lines changed

5 files changed

+87
-32
lines changed

src/builder/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl<'e> Builder<'e> {
3333
) -> Result<Self, String> {
3434
Self {
3535
config: config.clone(),
36-
root: Namespace::new_root(root),
36+
root: Namespace::new_root(root, config.clone()),
3737
_clang: clang,
3838
index,
3939
args,

src/builder/namespace.rs

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
use std::collections::HashMap;
1+
use std::{collections::HashMap, sync::Arc};
22

33
use clang::{Entity, EntityKind};
44

5-
use crate::url::UrlPath;
5+
use crate::{config::Config, url::UrlPath};
66

77
use super::{
8-
traits::{ASTEntry, BuildResult, EntityMethods, Entry, NavItem},
98
builder::Builder,
109
class::Class,
1110
function::Function,
1211
struct_::Struct,
12+
traits::{ASTEntry, BuildResult, EntityMethods, Entry, NavItem},
1313
};
1414

1515
pub enum CppItemKind {
@@ -23,7 +23,9 @@ impl CppItemKind {
2323
pub fn from(entity: &Entity) -> Option<Self> {
2424
match entity.get_kind() {
2525
EntityKind::StructDecl => Some(Self::Struct),
26-
EntityKind::ClassDecl | EntityKind::ClassTemplate | EntityKind::ClassTemplatePartialSpecialization => Some(Self::Class),
26+
EntityKind::ClassDecl
27+
| EntityKind::ClassTemplate
28+
| EntityKind::ClassTemplatePartialSpecialization => Some(Self::Class),
2729
EntityKind::FunctionDecl | EntityKind::FunctionTemplate => Some(Self::Function),
2830
EntityKind::Namespace => Some(Self::Namespace),
2931
_ => None,
@@ -48,7 +50,11 @@ pub enum CppItem<'e> {
4850
}
4951

5052
impl<'e> CppItem<'e> {
51-
fn get(&'e self, matcher: &dyn Fn(&dyn ASTEntry<'e>) -> bool, out: &mut Vec<&'e dyn ASTEntry<'e>>) {
53+
fn get(
54+
&'e self,
55+
matcher: &dyn Fn(&dyn ASTEntry<'e>) -> bool,
56+
out: &mut Vec<&'e dyn ASTEntry<'e>>,
57+
) {
5258
match self {
5359
CppItem::Namespace(ns) => {
5460
if matcher(ns) {
@@ -57,22 +63,22 @@ impl<'e> CppItem<'e> {
5763
for entry in ns.entries.values() {
5864
entry.get(&matcher, out);
5965
}
60-
},
66+
}
6167
CppItem::Class(cls) => {
6268
if matcher(cls) {
6369
out.push(cls);
6470
}
65-
},
71+
}
6672
CppItem::Struct(cls) => {
6773
if matcher(cls) {
6874
out.push(cls);
6975
}
70-
},
76+
}
7177
CppItem::Function(fun) => {
7278
if matcher(fun) {
7379
out.push(fun);
7480
}
75-
},
81+
}
7682
}
7783
}
7884
}
@@ -142,35 +148,50 @@ pub struct Namespace<'e> {
142148
}
143149

144150
impl<'e> Namespace<'e> {
145-
pub fn new(entity: Entity<'e>) -> Self {
151+
pub fn new(entity: Entity<'e>, config: Arc<Config>) -> Self {
146152
let mut ret = Self {
147153
entity,
148154
is_root: false,
149155
entries: HashMap::new(),
150156
};
151-
ret.load_entries();
157+
ret.load_entries(config);
152158
ret
153159
}
154160

155-
pub fn new_root(entity: Entity<'e>) -> Self {
161+
pub fn new_root(entity: Entity<'e>, config: Arc<Config>) -> Self {
156162
let mut ret = Self {
157163
entity,
158164
is_root: true,
159165
entries: HashMap::new(),
160166
};
161-
ret.load_entries();
167+
ret.load_entries(config);
162168
ret
163169
}
164170

165-
fn load_entries(&mut self) {
171+
fn load_entries(&mut self, config: Arc<Config>) {
166172
for child in &self.entity.get_children() {
167-
if child.is_in_system_header() || child.get_name().is_none() {
173+
// skip unnamed items
174+
if child.get_name().is_none() {
168175
continue;
169176
}
177+
178+
// skip stuff from external headers
179+
if child.is_in_system_header() && child.get_allowed_external_lib(config.clone()).is_none() {
180+
continue;
181+
}
182+
183+
// skips specialization of std stuff
184+
let is_parent_std = child
185+
.get_semantic_parent()
186+
.map_or(false, |f| f.get_name().as_deref() == Some("std"));
187+
if is_parent_std {
188+
continue;
189+
}
190+
170191
if let Some(kind) = CppItemKind::from(child) {
171192
match kind {
172193
CppItemKind::Namespace => {
173-
let entry = Namespace::new(*child);
194+
let entry = Namespace::new(*child, config.clone());
174195
// Merge existing entries of namespace
175196
if let Some(key) = self.entries.get_mut(&entry.name()) {
176197
if let CppItem::Namespace(ns) = key {
@@ -206,7 +227,7 @@ impl<'e> Namespace<'e> {
206227
}
207228
}
208229

209-
// so apparently if you make this a <M: Fn(&dyn ASTEntry<'e>) -> bool>
230+
// so apparently if you make this a <M: Fn(&dyn ASTEntry<'e>) -> bool>
210231
// rustc crashes
211232
pub fn get(&'e self, matcher: &dyn Fn(&dyn ASTEntry<'e>) -> bool) -> Vec<&'e dyn ASTEntry<'e>> {
212233
let mut res = Vec::new();
@@ -252,9 +273,10 @@ impl<'e> Entry<'e> for Namespace<'e> {
252273
fn url(&self) -> UrlPath {
253274
if self.is_root {
254275
UrlPath::new()
255-
}
256-
else {
257-
self.entity.rel_docs_url().expect("Unable to get namespace URL")
276+
} else {
277+
self.entity
278+
.rel_docs_url()
279+
.expect("Unable to get namespace URL")
258280
}
259281
}
260282
}

src/builder/shared.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -321,11 +321,14 @@ pub fn fmt_section(title: &str, data: Vec<Html>) -> Html {
321321
}
322322

323323
pub fn fmt_header_link(entity: &Entity, config: Arc<Config>) -> Html {
324-
if let Some(link) = entity.github_url(config.clone()) &&
325-
let Some(path) = entity.include_path(config.clone()) &&
326-
let Some(src) = entity.config_source(config)
324+
if let Some(link) = entity.github_url(config.clone())
325+
&& let Some(path) = entity.include_path(config.clone())
327326
{
328-
let disabled = !src.exists_online;
327+
let exists_online = entity
328+
.config_source(config.clone())
329+
.map(|s| s.exists_online)
330+
.unwrap_or(true);
331+
let disabled = !exists_online;
329332
HtmlElement::new("a")
330333
.with_attr_opt("href", (!disabled).then_some(link))
331334
.with_class("header-link")

src/builder/traits.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{path::PathBuf, sync::Arc, collections::HashMap};
55
use tokio::task::JoinHandle;
66

77
use crate::{
8-
config::{Config, Source},
8+
config::{Config, ExternalLib, Source},
99
html::{Html, HtmlElement, HtmlList, HtmlText},
1010
url::UrlPath,
1111
};
@@ -52,6 +52,9 @@ pub trait EntityMethods<'e> {
5252

5353
/// Same as extract_source_string, but removes new lines, double spaces, and leading/trailing whitespace
5454
fn extract_source_string_cleaned(&self) -> Option<String>;
55+
56+
/// Checks if the entitiy is in one of the allowed external libraries
57+
fn get_allowed_external_lib(&self, config: Arc<Config>) -> Option<Arc<ExternalLib>>;
5558
}
5659

5760
impl<'e> EntityMethods<'e> for Entity<'e> {
@@ -106,13 +109,10 @@ impl<'e> EntityMethods<'e> for Entity<'e> {
106109
}
107110

108111
fn github_url(&self, config: Arc<Config>) -> Option<String> {
109-
// If this is an std item, redirect to cppreference instead
110112
if self.full_name().first().is_some_and(|n| n == "std") {
111-
Some(format!(
112-
"https://en.cppreference.com/w/cpp/{}/{}",
113-
self.definition_file()?.file_name()?.to_str()?,
114-
self.get_name()?
115-
))
113+
unreachable!("Shouldn't be trying to link to a stl header - {:?}", self.get_name())
114+
} else if let Some(lib) = self.get_allowed_external_lib(config.clone()) {
115+
Some(lib.repository.clone())
116116
} else {
117117
Some(
118118
config.project.tree.clone()?
@@ -122,6 +122,9 @@ impl<'e> EntityMethods<'e> for Entity<'e> {
122122
}
123123

124124
fn include_path(&self, config: Arc<Config>) -> Option<UrlPath> {
125+
if self.is_in_system_header() {
126+
return UrlPath::part(self.header(config.clone())?.file_name()?.to_string_lossy().as_ref()).into()
127+
}
125128
UrlPath::try_from(&self.header(config.clone())?)
126129
.ok()?
127130
.strip_prefix(&self.config_source(config)?.dir)
@@ -151,6 +154,11 @@ impl<'e> EntityMethods<'e> for Entity<'e> {
151154
}
152155
}
153156
}
157+
// remove leading anon namespaces
158+
let mut ancestors: Vec<_> = ancestors
159+
.into_iter()
160+
.skip_while(|e| e.get_name().is_none())
161+
.collect();
154162
ancestors.push(*self);
155163
ancestors
156164
}
@@ -214,6 +222,22 @@ impl<'e> EntityMethods<'e> for Entity<'e> {
214222
.intersperse(" ")
215223
.collect())
216224
}
225+
226+
fn get_allowed_external_lib(&self, config: Arc<Config>) -> Option<Arc<ExternalLib>> {
227+
self.is_in_system_header()
228+
.then(|| self.get_location())
229+
.flatten()
230+
.and_then(|x| x.get_file_location().file)
231+
.and_then(|file| {
232+
let path = file.get_path();
233+
let path = path.to_string_lossy();
234+
config
235+
.external_libs
236+
.as_ref()
237+
.and_then(|x| x.iter().find(|f| path.contains(&f.pattern)))
238+
})
239+
.cloned()
240+
}
217241
}
218242

219243
#[derive(Clone)]

src/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ decl_config! {
118118
exists_online: bool = true,
119119
}
120120

121+
struct ExternalLib {
122+
pattern: String,
123+
repository: String,
124+
}
125+
121126
struct Config {
122127
project {
123128
name: String,
@@ -126,6 +131,7 @@ decl_config! {
126131
tree?: String,
127132
icon?: PathBuf,
128133
},
134+
external_libs?: Vec<Arc<ExternalLib>>,
129135
tutorials? {
130136
dir: PathBuf,
131137
assets: Vec<PathBuf> as parse_glob = Vec::new(),

0 commit comments

Comments
 (0)