opencv_binding_generator/
debug.rs1use std::borrow::Cow;
2use std::fmt::Display;
3use std::path::{Path, PathBuf};
4use std::sync::LazyLock;
5use std::{env, fmt};
6
7use clang::Entity;
8use dunce::canonicalize;
9
10pub static EMIT_DEBUG: LazyLock<bool> = LazyLock::new(|| env::var("OPENCV_BINDING_GENERATOR_EMIT_DEBUG").is_ok_and(|v| v == "1"));
11
12#[derive(Clone, Debug)]
13pub struct LocationName<'me> {
14 pub location: DefinitionLocation,
15 pub name: Cow<'me, str>,
16}
17
18impl<'me> LocationName<'me> {
19 pub fn new(location: DefinitionLocation, name: impl Into<Cow<'me, str>>) -> Self {
20 Self {
21 location,
22 name: name.into(),
23 }
24 }
25}
26
27#[derive(Clone, Debug)]
28pub enum DefinitionLocation {
29 Generated,
30 File(PathBuf, u32),
31}
32
33impl DefinitionLocation {
34 pub fn as_file(&self) -> Option<(&Path, u32)> {
35 match self {
36 DefinitionLocation::Generated => None,
37 DefinitionLocation::File(path, line) => Some((path, *line)),
38 }
39 }
40}
41
42impl Display for DefinitionLocation {
43 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
44 match self {
45 Self::Generated => f.write_str("generated"),
46 Self::File(file, line) => {
47 write!(f, "{}:{line}", canonicalize(file).expect("Can't canonicalize path").display())
48 }
49 }
50 }
51}
52
53pub trait NameDebug<'me> {
54 fn file_line_name(self) -> LocationName<'me>;
55
56 fn get_debug(self) -> String
57 where
58 Self: Sized,
59 {
60 if *EMIT_DEBUG {
61 let LocationName { location, name } = self.file_line_name();
62 format!("// {name} {location}")
63 } else {
64 "".to_string()
65 }
66 }
67}
68
69impl NameDebug<'_> for &Entity<'_> {
70 fn file_line_name(self) -> LocationName<'static> {
71 let loc = self.get_location().expect("Can't get entity location").get_file_location();
72 LocationName::new(
73 DefinitionLocation::File(loc.file.map(|f| f.get_path()).expect("Can't get file for debug"), loc.line),
74 self
75 .get_display_name()
76 .unwrap_or_else(|| "<unknown display name>".to_string()),
77 )
78 }
79}