GCC Code Coverage Report


Directory: ./
File: src/BackEnd/nanobind_generator.cpp
Date: 2026-01-30 16:30:53
Exec Total Coverage
Lines: 55 63 87.3%
Functions: 3 3 100.0%
Branches: 107 139 77.0%

Line Branch Exec Source
1 /***************************************
2 Auteur : Thibaut Oprinsen
3 Mail : thibaut.oprinsen@lapp.in2p3.fr
4 Licence : CeCILL-C
5 ****************************************/
6
7 #include <set>
8 #include "header_generator.h"
9 #include "nanobind_generator.h"
10 #include "phoenix_color.h"
11 #include "openFileStream.h"
12
13 ///Generate nanobind wrapper class
14 /** @param manager : PTraitBackendManager which handles all trait backend
15 * @param baseFileName : base file name to be used (without path and extension)
16 * @param sourceFile : source file to be saved
17 * @param headerFile : header to be used with this source file
18 * @param extraInclude : extra include to be added in the source file
19 * @param vecClassConfig : vector of configuration of the classes to be used
20 * @param mode : mode of the generator
21 * @return true on success, false otherwise
22 */
23 2 bool generator_nanobind_class(const PNanobindTraitBackendManager &manager, PPath& baseFileName, const PPath &sourceFile, const PPath &headerFile, const PVecPath &extraInclude, const PVecClassConfig &vecClassConfig, const GeneratorMode &mode){
24
2/3
✓ Branch 0 (2→3) taken 2 times.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→13) taken 2 times.
2 if(baseFileName == ""){
25 std::cerr << termRed() << "generator_class_cpp : baseFileName is empty" << termDefault() << std::endl;
26 return false;
27 }
28
1/1
✓ Branch 0 (13→14) taken 2 times.
2 std::ofstream fs;
29
2/3
✓ Branch 0 (14→15) taken 2 times.
✗ Branch 2 (15→16) not taken.
✓ Branch 3 (15→17) taken 2 times.
2 if(!openFileStream(fs, sourceFile)){return false;}
30
1/1
✓ Branch 0 (17→18) taken 2 times.
2 licenceSave(fs);
31
7/7
✓ Branch 0 (18→19) taken 2 times.
✓ Branch 2 (19→20) taken 2 times.
✓ Branch 4 (20→21) taken 2 times.
✓ Branch 6 (21→22) taken 2 times.
✓ Branch 8 (22→23) taken 2 times.
✓ Branch 10 (23→24) taken 2 times.
✓ Branch 12 (24→25) taken 2 times.
2 fs << std::endl << "#include \"" << headerFile.getFileName() << "\"" << std::endl << std::endl;
32
2/2
✓ Branch 0 (26→27) taken 2 times.
✓ Branch 2 (27→28) taken 2 times.
2 fs << "#include <nanobind/nanobind.h>" << std::endl;
33 2 std::set<std::string> extraIncludes;
34
2/2
✓ Branch 0 (43→30) taken 2 times.
✓ Branch 1 (43→44) taken 2 times.
8 for (std::vector<PClassConfig>::const_iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
35
1/1
✓ Branch 0 (32→33) taken 2 times.
4 manager.headerExtraInclude(extraIncludes, *it, mode);
36 }
37
2/2
✓ Branch 0 (51→46) taken 3 times.
✓ Branch 1 (51→52) taken 2 times.
5 for (const std::string & include : extraIncludes){
38
2/2
✓ Branch 0 (47→48) taken 3 times.
✓ Branch 2 (48→49) taken 3 times.
3 fs << include << std::endl;
39 }
40
3/3
✓ Branch 0 (52→53) taken 2 times.
✓ Branch 2 (53→54) taken 2 times.
✓ Branch 4 (54→55) taken 2 times.
2 fs << "\nnamespace nb = nanobind;" << std::endl << std::endl;
41
3/3
✓ Branch 0 (55→56) taken 2 times.
✓ Branch 2 (56→57) taken 2 times.
✓ Branch 4 (57→58) taken 2 times.
2 PString fileModuleName = baseFileName.toLower() + "_module";
42
4/4
✓ Branch 0 (60→61) taken 2 times.
✓ Branch 2 (61→62) taken 2 times.
✓ Branch 4 (62→63) taken 2 times.
✓ Branch 6 (63→64) taken 2 times.
2 fs << "NB_MODULE(" << fileModuleName << ", m) {" << std::endl;
43
4/4
✓ Branch 0 (64→65) taken 2 times.
✓ Branch 2 (65→66) taken 2 times.
✓ Branch 4 (66→67) taken 2 times.
✓ Branch 6 (67→68) taken 2 times.
2 fs << "\tm.doc() = \"Nanobind bindings for " << baseFileName << " classes\";\n" << std::endl;
44
45
2/2
✓ Branch 0 (108→69) taken 2 times.
✓ Branch 1 (108→109) taken 2 times.
8 for (std::vector<PClassConfig>::const_iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
46
8/8
✓ Branch 0 (69→70) taken 2 times.
✓ Branch 2 (72→73) taken 2 times.
✓ Branch 4 (73→74) taken 2 times.
✓ Branch 6 (74→75) taken 2 times.
✓ Branch 8 (77→78) taken 2 times.
✓ Branch 10 (78→79) taken 2 times.
✓ Branch 12 (79→80) taken 2 times.
✓ Branch 14 (80→81) taken 2 times.
6 fs << "\tnb::class_<" << it->getName() << ">(m, \"" << it->getName() << "\")" << std::endl;
47
2/2
✓ Branch 0 (81→82) taken 2 times.
✓ Branch 2 (82→83) taken 2 times.
2 fs << "\t\t//Attributes" << std::endl;
48
1/1
✓ Branch 0 (85→86) taken 2 times.
4 manager.registerProperty(fs, *it, mode);
49
1/1
✓ Branch 0 (88→89) taken 2 times.
4 manager.registerConstructor(fs, *it, mode);
50
1/1
✓ Branch 0 (91→92) taken 2 times.
4 manager.registerStaticMethod(fs, *it, mode);
51
52
1/1
✓ Branch 0 (94→95) taken 2 times.
4 manager.registerMethod(fs, *it, mode);
53
3/3
✓ Branch 0 (95→96) taken 2 times.
✓ Branch 2 (96→97) taken 2 times.
✓ Branch 4 (97→98) taken 2 times.
2 fs << ";" << std::endl << std::endl;
54
55 }
56
2/2
✓ Branch 0 (109→110) taken 2 times.
✓ Branch 2 (110→111) taken 2 times.
2 fs << "}" << std::endl; // Close NB_MODULE
57
1/1
✓ Branch 0 (111→112) taken 2 times.
2 fs.close();
58 2 return true;
59 2 }
60
61 2 bool generator_nanobind_test(const PNanobindTraitBackendManager & manager, const PPath & outputTestDir, const std::vector<PClassConfig> & vecClassConfig, const PString & projectName, const PPath & baseFileName, const GeneratorMode & mode){
62
2/2
✓ Branch 0 (71→3) taken 2 times.
✓ Branch 1 (71→72) taken 2 times.
8 for(std::vector<PClassConfig>::const_iterator it(vecClassConfig.begin()); it != vecClassConfig.end(); ++it){
63
2/2
✓ Branch 0 (5→6) taken 2 times.
✓ Branch 2 (6→7) taken 2 times.
2 PString name = it->getName();
64
7/7
✓ Branch 0 (7→8) taken 2 times.
✓ Branch 2 (8→9) taken 2 times.
✓ Branch 4 (9→10) taken 2 times.
✓ Branch 6 (10→11) taken 2 times.
✓ Branch 8 (11→12) taken 2 times.
✓ Branch 10 (12→13) taken 2 times.
✓ Branch 12 (13→14) taken 2 times.
2 PPath outputCurrentTestDir(outputTestDir + PString("/TEST_") + name.toUpper() + "_BINDINGS");
65
2/3
✓ Branch 0 (20→21) taken 2 times.
✗ Branch 2 (21→22) not taken.
✓ Branch 3 (21→27) taken 2 times.
2 if(!outputCurrentTestDir.createDirectory()){
66 std::cerr << "generator_class_test : cannot create TEST directory '"<<outputCurrentTestDir<<"'" << std::endl;
67 return false;
68 }
69
1/1
✓ Branch 0 (27→28) taken 2 times.
2 std::ofstream fs;
70
8/9
✓ Branch 0 (28→29) taken 2 times.
✓ Branch 2 (29→30) taken 2 times.
✓ Branch 4 (30→31) taken 2 times.
✓ Branch 6 (31→32) taken 2 times.
✓ Branch 8 (32→33) taken 2 times.
✓ Branch 10 (33→34) taken 2 times.
✓ Branch 12 (34→35) taken 2 times.
✗ Branch 14 (41→42) not taken.
✓ Branch 15 (41→43) taken 2 times.
2 if(!openFileStream(fs, PPath(outputCurrentTestDir + PString("/test_") + name + "_binding.py"))){return false;}
71
1/1
✓ Branch 0 (43→44) taken 2 times.
2 manager.headerTestInclude(fs, mode, baseFileName);
72
1/1
✓ Branch 0 (46→47) taken 2 times.
4 manager.testFunction(fs, *it, mode, baseFileName);
73
1/1
✓ Branch 0 (47→48) taken 2 times.
2 fs.close();
74 2 }
75 2 return true;
76 }
77
78 ///Generate the full sources and related unit tests from configuration
79 /** @param manager : PTraitBackendManager which handles all trait backend
80 * @param projectParam : description of classes and how and where to generate sources and test
81 * @return true on success, false otherwise
82 */
83 1 bool generator_nanobind_full(const PNanobindTraitBackendManager & manager, const ProjectParam & projectParam)
84 {
85 1 bool b(true);
86 1 b &= projectParam.outputSourceDir.createDirectory();
87 1 b &= projectParam.outputTestDir.createDirectory();
88 1 const PVecDataConfig & vecDataConfig = projectParam.vecDataConfig;
89
90
2/2
✓ Branch 0 (74→6) taken 2 times.
✓ Branch 1 (74→75) taken 1 times.
4 for(const PDataConfig & config : vecDataConfig){
91
1/1
✓ Branch 0 (8→9) taken 2 times.
2 const PVecPath & extraInclude = config.getVecInclude();
92
4/4
✓ Branch 0 (9→10) taken 2 times.
✓ Branch 2 (10→11) taken 2 times.
✓ Branch 4 (11→12) taken 2 times.
✓ Branch 6 (12→13) taken 2 times.
2 PPath baseFileName = config.getFileName().getFileName().eraseExtension();
93
4/4
✓ Branch 0 (14→15) taken 2 times.
✓ Branch 2 (15→16) taken 2 times.
✓ Branch 4 (16→17) taken 2 times.
✓ Branch 6 (17→18) taken 2 times.
2 PPath headerFile = projectParam.outputSourceDir / PPath(baseFileName + ".h");
94
4/4
✓ Branch 0 (21→22) taken 2 times.
✓ Branch 2 (22→23) taken 2 times.
✓ Branch 4 (23→24) taken 2 times.
✓ Branch 6 (24→25) taken 2 times.
2 PPath sourceFile = projectParam.outputSourceDir / PPath(baseFileName + "_binding.cpp");
95
3/4
✓ Branch 0 (28→29) taken 2 times.
✓ Branch 2 (29→30) taken 2 times.
✗ Branch 4 (30→31) not taken.
✓ Branch 5 (30→42) taken 2 times.
2 if(!generator_nanobind_class(manager, baseFileName, sourceFile, headerFile, extraInclude, config.getVecClassConfig(), projectParam.mode)){
96 std::cerr << termRed() << "generator_nanobind_full : cannot generate nanobind sources at '"<<projectParam.outputSourceDir<<"'" << termDefault() << std::endl;
97 b = false; //best effort strategy
98 }
99
3/3
✓ Branch 0 (42→43) taken 2 times.
✓ Branch 2 (43→44) taken 2 times.
✓ Branch 4 (44→45) taken 2 times.
2 PPath outputCurrentTestDir = projectParam.outputTestDir / PPath("TEST_PYTHON_BINDINGS");
100
3/4
✓ Branch 0 (47→48) taken 2 times.
✓ Branch 2 (48→49) taken 2 times.
✗ Branch 4 (49→50) not taken.
✓ Branch 5 (49→61) taken 2 times.
2 if(!generator_nanobind_test(manager, outputCurrentTestDir, config.getVecClassConfig(), projectParam.name, baseFileName, projectParam.mode)){
101 std::cerr << termRed() << "generator_nanobind_full : cannot generate nanobind tests at '"<<projectParam.outputTestDir<<"'" << termDefault() << std::endl;
102 b = false; //best effort strategy
103 }
104 2 }
105 1 return b;
106 }
107