Doxygen
Loading...
Searching...
No Matches
sqlite3gen.cpp
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2015 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16#include <stdlib.h>
17#include <stdio.h>
18#include <sstream>
19
20#include "settings.h"
21#include "message.h"
22
23
24#include "sqlite3gen.h"
25#include "doxygen.h"
26#include "xmlgen.h"
27#include "xmldocvisitor.h"
28#include "config.h"
29#include "util.h"
30#include "outputlist.h"
31#include "docparser.h"
32#include "docnode.h"
33#include "language.h"
34
35#include "version.h"
36#include "dot.h"
37#include "arguments.h"
38#include "classlist.h"
39#include "filedef.h"
40#include "namespacedef.h"
41#include "filename.h"
42#include "groupdef.h"
43#include "membername.h"
44#include "memberdef.h"
45#include "pagedef.h"
46#include "dirdef.h"
47#include "section.h"
48#include "fileinfo.h"
49#include "dir.h"
50#include "datetime.h"
51#include "moduledef.h"
52
53#include <sys/stat.h>
54#include <string.h>
55#include <sqlite3.h>
56
57// enable to show general debug messages
58// #define SQLITE3_DEBUG
59
60// enable to print all executed SQL statements.
61// I recommend using the smallest possible input list.
62// #define SQLITE3_DEBUG_SQL
63
64# ifdef SQLITE3_DEBUG
65# define DBG_CTX(x) printf x
66# else // SQLITE3_DEBUG
67# define DBG_CTX(x) do { } while(0)
68# endif
69
70# ifdef SQLITE3_DEBUG_SQL
71// used by sqlite3_trace in generateSqlite3()
72static void sqlLog(void *dbName, const char *sql){
73 msg("SQL: '{}'\n", sql);
74}
75# endif
76
77const char * table_schema[][2] = {
78 /* TABLES */
79 { "meta",
80 "CREATE TABLE IF NOT EXISTS meta (\n"
81 "\t-- Information about this db and how it was generated.\n"
82 "\t-- Doxygen info\n"
83 "\tdoxygen_version TEXT PRIMARY KEY NOT NULL,\n"
84 /*
85 Doxygen's version is likely to rollover much faster than the schema, and
86 at least until it becomes a core output format, we might want to make
87 fairly large schema changes even on minor iterations for Doxygen itself.
88 If these tools just track a predefined semver schema version that can
89 iterate independently, it *might* not be as hard to keep them in sync?
90 */
91 "\tschema_version TEXT NOT NULL, -- Schema-specific semver\n"
92 "\t-- run info\n"
93 "\tgenerated_at TEXT NOT NULL,\n"
94 "\tgenerated_on TEXT NOT NULL,\n"
95 "\t-- project info\n"
96 "\tproject_name TEXT NOT NULL,\n"
97 "\tproject_number TEXT,\n"
98 "\tproject_brief TEXT\n"
99 ");"
100 },
101 { "includes",
102 "CREATE TABLE IF NOT EXISTS includes (\n"
103 "\t-- #include relations.\n"
104 "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
105 "\tlocal INTEGER NOT NULL,\n"
106 "\tsrc_id INTEGER NOT NULL REFERENCES path, -- File id of the includer.\n"
107 "\tdst_id INTEGER NOT NULL REFERENCES path, -- File id of the includee.\n"
108 /*
109 In theory we could include name here to be informationally equivalent
110 with the XML, but I don't see an obvious use for it.
111 */
112 "\tUNIQUE(local, src_id, dst_id) ON CONFLICT IGNORE\n"
113 ");"
114 },
115 { "contains",
116 "CREATE TABLE IF NOT EXISTS contains (\n"
117 "\t-- inner/outer relations (file, namespace, dir, class, group, page)\n"
118 "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
119 "\tinner_rowid INTEGER NOT NULL REFERENCES compounddef,\n"
120 "\touter_rowid INTEGER NOT NULL REFERENCES compounddef\n"
121 ");"
122 },
123 /* TODO: Path can also share rowids with refid/compounddef/def. (It could
124 * even collapse into that table...)
125 *
126 * I took a first swing at this by changing insertPath() to:
127 * - accept a FileDef
128 * - make its own call to insertRefid
129 * - return a refid struct.
130 *
131 * I rolled this back when I had trouble getting a FileDef for all types
132 * (PageDef in particular).
133 *
134 * Note: all columns referencing path would need an update.
135 */
136 { "path",
137 "CREATE TABLE IF NOT EXISTS path (\n"
138 "\t-- Paths of source files and includes.\n"
139 "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
140 "\ttype INTEGER NOT NULL, -- 1:file 2:dir\n"
141 "\tlocal INTEGER NOT NULL,\n"
142 "\tfound INTEGER NOT NULL,\n"
143 "\tname TEXT NOT NULL\n"
144 ");"
145 },
146 { "refid",
147 "CREATE TABLE IF NOT EXISTS refid (\n"
148 "\t-- Distinct refid for all documented entities.\n"
149 "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
150 "\trefid TEXT NOT NULL UNIQUE\n"
151 ");"
152 },
153 { "xrefs",
154 "CREATE TABLE IF NOT EXISTS xrefs (\n"
155 "\t-- Cross-reference relation\n"
156 "\t-- (combines xml <referencedby> and <references> nodes).\n"
157 "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
158 "\tsrc_rowid INTEGER NOT NULL REFERENCES refid, -- referrer id.\n"
159 "\tdst_rowid INTEGER NOT NULL REFERENCES refid, -- referee id.\n"
160 "\tcontext TEXT NOT NULL, -- inline, argument, initializer\n"
161 "\t-- Just need to know they link; ignore duplicates.\n"
162 "\tUNIQUE(src_rowid, dst_rowid, context) ON CONFLICT IGNORE\n"
163 ");\n"
164 },
165 { "memberdef",
166 "CREATE TABLE IF NOT EXISTS memberdef (\n"
167 "\t-- All processed identifiers.\n"
168 "\trowid INTEGER PRIMARY KEY NOT NULL,\n"
169 "\tname TEXT NOT NULL,\n"
170 "\tdefinition TEXT,\n"
171 "\ttype TEXT,\n"
172 "\targsstring TEXT,\n"
173 "\tscope TEXT,\n"
174 "\tinitializer TEXT,\n"
175 "\tbitfield TEXT,\n"
176 "\tread TEXT,\n"
177 "\twrite TEXT,\n"
178 "\tprot INTEGER DEFAULT 0, -- 0:public 1:protected 2:private 3:package\n"
179 "\tstatic INTEGER DEFAULT 0, -- 0:no 1:yes\n"
180 "\textern INTEGER DEFAULT 0, -- 0:no 1:yes\n"
181 "\tconst INTEGER DEFAULT 0, -- 0:no 1:yes\n"
182 "\texplicit INTEGER DEFAULT 0, -- 0:no 1:yes\n"
183 "\tinline INTEGER DEFAULT 0, -- 0:no 1:yes 2:both (set after encountering inline and not-inline)\n"
184 "\tfinal INTEGER DEFAULT 0, -- 0:no 1:yes\n"
185 "\tsealed INTEGER DEFAULT 0, -- 0:no 1:yes\n"
186 "\tnew INTEGER DEFAULT 0, -- 0:no 1:yes\n"
187 "\toptional INTEGER DEFAULT 0, -- 0:no 1:yes\n"
188 "\trequired INTEGER DEFAULT 0, -- 0:no 1:yes\n"
189 "\tvolatile INTEGER DEFAULT 0, -- 0:no 1:yes\n"
190 "\tvirt INTEGER DEFAULT 0, -- 0:no 1:virtual 2:pure-virtual\n"
191 "\tmutable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
192 "\tinitonly INTEGER DEFAULT 0, -- 0:no 1:yes\n"
193 "\tattribute INTEGER DEFAULT 0, -- 0:no 1:yes\n"
194 "\tproperty INTEGER DEFAULT 0, -- 0:no 1:yes\n"
195 "\treadonly INTEGER DEFAULT 0, -- 0:no 1:yes\n"
196 "\tbound INTEGER DEFAULT 0, -- 0:no 1:yes\n"
197 "\tconstrained INTEGER DEFAULT 0, -- 0:no 1:yes\n"
198 "\ttransient INTEGER DEFAULT 0, -- 0:no 1:yes\n"
199 "\tmaybevoid INTEGER DEFAULT 0, -- 0:no 1:yes\n"
200 "\tmaybedefault INTEGER DEFAULT 0, -- 0:no 1:yes\n"
201 "\tmaybeambiguous INTEGER DEFAULT 0, -- 0:no 1:yes\n"
202 "\treadable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
203 "\twritable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
204 "\tgettable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
205 "\tprivategettable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
206 "\tprotectedgettable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
207 "\tsettable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
208 "\tprivatesettable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
209 "\tprotectedsettable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
210 "\taccessor INTEGER DEFAULT 0, -- 0:no 1:assign 2:copy 3:retain 4:string 5:weak\n"
211 "\taddable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
212 "\tremovable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
213 "\traisable INTEGER DEFAULT 0, -- 0:no 1:yes\n"
214 "\tkind TEXT NOT NULL, -- 'macro definition' 'function' 'variable' 'typedef' 'enumeration' 'enumvalue' 'signal' 'slot' 'friend' 'dcop' 'property' 'event' 'interface' 'service'\n"
215 "\tbodystart INTEGER DEFAULT 0, -- starting line of definition\n"
216 "\tbodyend INTEGER DEFAULT 0, -- ending line of definition\n"
217 "\tbodyfile_id INTEGER REFERENCES path, -- file of definition\n"
218 "\tfile_id INTEGER NOT NULL REFERENCES path, -- file where this identifier is located\n"
219 "\tline INTEGER NOT NULL, -- line where this identifier is located\n"
220 "\tcolumn INTEGER NOT NULL, -- column where this identifier is located\n"
221 "\tdetaileddescription TEXT,\n"
222 "\tbriefdescription TEXT,\n"
223 "\tinbodydescription TEXT,\n"
224 "\tFOREIGN KEY (rowid) REFERENCES refid (rowid)\n"
225 ");"
226 },
227 { "member",
228 "CREATE TABLE IF NOT EXISTS member (\n"
229 "\t-- Memberdef <-> containing compound relation.\n"
230 "\t-- Similar to XML listofallmembers.\n"
231 "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
232 "\tscope_rowid INTEGER NOT NULL REFERENCES compounddef,\n"
233 "\tmemberdef_rowid INTEGER NOT NULL REFERENCES memberdef,\n"
234 "\tprot INTEGER NOT NULL,\n"
235 "\tvirt INTEGER NOT NULL,\n"
236 "\tUNIQUE(scope_rowid, memberdef_rowid)\n"
237 ");"
238 },
239 { "reimplements",
240 "CREATE TABLE IF NOT EXISTS reimplements (\n"
241 "\t-- Inherited member reimplementation relations.\n"
242 "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
243 "\tmemberdef_rowid INTEGER NOT NULL REFERENCES memberdef, -- reimplementing memberdef id.\n"
244 "\treimplemented_rowid INTEGER NOT NULL REFERENCES memberdef, -- reimplemented memberdef id.\n"
245 "\tUNIQUE(memberdef_rowid, reimplemented_rowid) ON CONFLICT IGNORE\n"
246 ");\n"
247 },
248 { "compounddef",
249 "CREATE TABLE IF NOT EXISTS compounddef (\n"
250 "\t-- Class/struct definitions.\n"
251 "\trowid INTEGER PRIMARY KEY NOT NULL,\n"
252 "\tname TEXT NOT NULL,\n"
253 "\ttitle TEXT,\n"
254 // probably won't be empty '' or unknown, but the source *could* return them...
255 "\tkind TEXT NOT NULL, -- 'category' 'class' 'constants' 'dir' 'enum' 'example' 'exception' 'file' 'group' 'interface' 'library' 'module' 'namespace' 'package' 'page' 'protocol' 'service' 'singleton' 'struct' 'type' 'union' 'unknown' ''\n"
256 "\tprot INTEGER,\n"
257 "\tfile_id INTEGER NOT NULL REFERENCES path,\n"
258 "\tline INTEGER NOT NULL,\n"
259 "\tcolumn INTEGER NOT NULL,\n"
260 "\theader_id INTEGER REFERENCES path,\n"
261 "\tdetaileddescription TEXT,\n"
262 "\tbriefdescription TEXT,\n"
263 "\tFOREIGN KEY (rowid) REFERENCES refid (rowid)\n"
264 ");"
265 },
266 { "compoundref",
267 "CREATE TABLE IF NOT EXISTS compoundref (\n"
268 "\t-- Inheritance relation.\n"
269 "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
270 "\tbase_rowid INTEGER NOT NULL REFERENCES compounddef,\n"
271 "\tderived_rowid INTEGER NOT NULL REFERENCES compounddef,\n"
272 "\tprot INTEGER NOT NULL,\n"
273 "\tvirt INTEGER NOT NULL,\n"
274 "\tUNIQUE(base_rowid, derived_rowid)\n"
275 ");"
276 },
277 { "param",
278 "CREATE TABLE IF NOT EXISTS param (\n"
279 "\t-- All processed parameters.\n"
280 "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
281 "\tattributes TEXT,\n"
282 "\ttype TEXT,\n"
283 "\tdeclname TEXT,\n"
284 "\tdefname TEXT,\n"
285 "\tarray TEXT,\n"
286 "\tdefval TEXT,\n"
287 "\tbriefdescription TEXT\n"
288 ");"
289 "CREATE UNIQUE INDEX idx_param ON param\n"
290 "\t(type, defname);"
291 },
292 { "memberdef_param",
293 "CREATE TABLE IF NOT EXISTS memberdef_param (\n"
294 "\t-- Junction table for memberdef parameters.\n"
295 "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n"
296 "\tmemberdef_id INTEGER NOT NULL REFERENCES memberdef,\n"
297 "\tparam_id INTEGER NOT NULL REFERENCES param\n"
298 ");"
299 },
300};
301 const char * view_schema[][2] = {
302 /* VIEWS *
303 We'll set these up AFTER we build the database, so that they can be indexed,
304 but so we don't have to pay a performance penalty for inserts as we build.
305 */
306 {
307 /*
308 Makes all reference/relation tables easier to use. For example:
309 1. query xrefs and join this view on either xrefs.dst_rowid=def.rowid or
310 xrefs.src_rowid=def.rowid
311 2. get everything you need to output a list of references to/from an entity
312
313 Also supports simple name search/lookup for both compound and member types.
314
315 NOTES:
316 - summary for compounds generalizes title and briefdescription because
317 there's no single field that works as a quick introduction for both
318 pages and classes
319 - May be value in eventually extending this to fulltext or levenshtein
320 distance-driven lookup/search, but I'm avoiding these for now as it
321 takes some effort to enable them.
322 */
323 "def",
324 "CREATE VIEW IF NOT EXISTS def (\n"
325 "\t-- Combined summary of all -def types for easier joins.\n"
326 "\trowid,\n"
327 "\trefid,\n"
328 "\tkind,\n"
329 "\tname,\n"
330 "\tsummary"
331 ")\n"
332 "as SELECT \n"
333 "\trefid.rowid,\n"
334 "\trefid.refid,\n"
335 "\tmemberdef.kind,\n"
336 "\tmemberdef.name,\n"
337 "\tmemberdef.briefdescription \n"
338 "FROM refid \n"
339 "JOIN memberdef ON refid.rowid=memberdef.rowid \n"
340 "UNION ALL \n"
341 "SELECT \n"
342 "\trefid.rowid,\n"
343 "\trefid.refid,\n"
344 "\tcompounddef.kind,\n"
345 "\tcompounddef.name,\n"
346 "\tCASE \n"
347 "\t\tWHEN briefdescription IS NOT NULL \n"
348 "\t\tTHEN briefdescription \n"
349 "\t\tELSE title \n"
350 "\tEND summary\n"
351 "FROM refid \n"
352 "JOIN compounddef ON refid.rowid=compounddef.rowid;"
353 },
354 {
355 "local_file",
356 "CREATE VIEW IF NOT EXISTS local_file (\n"
357 "\t-- File paths found within the project.\n"
358 "\trowid,\n"
359 "\tfound,\n"
360 "\tname\n"
361 ")\n"
362 "as SELECT \n"
363 "\tpath.rowid,\n"
364 "\tpath.found,\n"
365 "\tpath.name\n"
366 "FROM path WHERE path.type=1 AND path.local=1 AND path.found=1;\n"
367 },
368 {
369 "external_file",
370 "CREATE VIEW IF NOT EXISTS external_file (\n"
371 "\t-- File paths outside the project (found or not).\n"
372 "\trowid,\n"
373 "\tfound,\n"
374 "\tname\n"
375 ")\n"
376 "as SELECT \n"
377 "\tpath.rowid,\n"
378 "\tpath.found,\n"
379 "\tpath.name\n"
380 "FROM path WHERE path.type=1 AND path.local=0;\n"
381 },
382 {
383 "inline_xrefs",
384 "CREATE VIEW IF NOT EXISTS inline_xrefs (\n"
385 "\t-- Crossrefs from inline member source.\n"
386 "\trowid,\n"
387 "\tsrc_rowid,\n"
388 "\tdst_rowid\n"
389 ")\n"
390 "as SELECT \n"
391 "\txrefs.rowid,\n"
392 "\txrefs.src_rowid,\n"
393 "\txrefs.dst_rowid\n"
394 "FROM xrefs WHERE xrefs.context='inline';\n"
395 },
396 {
397 "argument_xrefs",
398 "CREATE VIEW IF NOT EXISTS argument_xrefs (\n"
399 "\t-- Crossrefs from member def/decl arguments\n"
400 "\trowid,\n"
401 "\tsrc_rowid,\n"
402 "\tdst_rowid\n"
403 ")\n"
404 "as SELECT \n"
405 "\txrefs.rowid,\n"
406 "\txrefs.src_rowid,\n"
407 "\txrefs.dst_rowid\n"
408 "FROM xrefs WHERE xrefs.context='argument';\n"
409 },
410 {
411 "initializer_xrefs",
412 "CREATE VIEW IF NOT EXISTS initializer_xrefs (\n"
413 "\t-- Crossrefs from member initializers\n"
414 "\trowid,\n"
415 "\tsrc_rowid,\n"
416 "\tdst_rowid\n"
417 ")\n"
418 "as SELECT \n"
419 "\txrefs.rowid,\n"
420 "\txrefs.src_rowid,\n"
421 "\txrefs.dst_rowid\n"
422 "FROM xrefs WHERE xrefs.context='initializer';\n"
423 },
424 {
425 "inner_outer",
426 "CREATE VIEW IF NOT EXISTS inner_outer\n"
427 "\t-- Joins 'contains' relations to simplify inner/outer 'rel' queries.\n"
428 "as SELECT \n"
429 "\tinner.*,\n"
430 "\touter.*\n"
431 "FROM def as inner\n"
432 "\tJOIN contains ON inner.rowid=contains.inner_rowid\n"
433 "\tJOIN def AS outer ON outer.rowid=contains.outer_rowid;\n"
434 },
435 {
436 "rel",
437 "CREATE VIEW IF NOT EXISTS rel (\n"
438 "\t-- Boolean indicator of relations available for a given entity.\n"
439 "\t-- Join to (compound-|member-)def to find fetch-worthy relations.\n"
440 "\trowid,\n"
441 "\treimplemented,\n"
442 "\treimplements,\n"
443 "\tinnercompounds,\n"
444 "\toutercompounds,\n"
445 "\tinnerpages,\n"
446 "\touterpages,\n"
447 "\tinnerdirs,\n"
448 "\touterdirs,\n"
449 "\tinnerfiles,\n"
450 "\touterfiles,\n"
451 "\tinnerclasses,\n"
452 "\touterclasses,\n"
453 "\tinnernamespaces,\n"
454 "\touternamespaces,\n"
455 "\tinnergroups,\n"
456 "\toutergroups,\n"
457 "\tmembers,\n"
458 "\tcompounds,\n"
459 "\tsubclasses,\n"
460 "\tsuperclasses,\n"
461 "\tlinks_in,\n"
462 "\tlinks_out,\n"
463 "\targument_links_in,\n"
464 "\targument_links_out,\n"
465 "\tinitializer_links_in,\n"
466 "\tinitializer_links_out\n"
467 ")\n"
468 "as SELECT \n"
469 "\tdef.rowid,\n"
470 "\tEXISTS (SELECT rowid FROM reimplements WHERE reimplemented_rowid=def.rowid),\n"
471 "\tEXISTS (SELECT rowid FROM reimplements WHERE memberdef_rowid=def.rowid),\n"
472 "\t-- rowid/kind for inner, [rowid:1/kind:1] for outer\n"
473 "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid),\n"
474 "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid),\n"
475 "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='page'),\n"
476 "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='page'),\n"
477 "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='dir'),\n"
478 "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='dir'),\n"
479 "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='file'),\n"
480 "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='file'),\n"
481 "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind in (\n"
482 "'category','class','enum','exception','interface','module','protocol',\n"
483 "'service','singleton','struct','type','union'\n"
484 ")),\n"
485 "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1] in (\n"
486 "'category','class','enum','exception','interface','module','protocol',\n"
487 "'service','singleton','struct','type','union'\n"
488 ")),\n"
489 "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='namespace'),\n"
490 "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='namespace'),\n"
491 "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='group'),\n"
492 "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='group'),\n"
493 "\tEXISTS (SELECT rowid FROM member WHERE scope_rowid=def.rowid),\n"
494 "\tEXISTS (SELECT rowid FROM member WHERE memberdef_rowid=def.rowid),\n"
495 "\tEXISTS (SELECT rowid FROM compoundref WHERE base_rowid=def.rowid),\n"
496 "\tEXISTS (SELECT rowid FROM compoundref WHERE derived_rowid=def.rowid),\n"
497 "\tEXISTS (SELECT rowid FROM inline_xrefs WHERE dst_rowid=def.rowid),\n"
498 "\tEXISTS (SELECT rowid FROM inline_xrefs WHERE src_rowid=def.rowid),\n"
499 "\tEXISTS (SELECT rowid FROM argument_xrefs WHERE dst_rowid=def.rowid),\n"
500 "\tEXISTS (SELECT rowid FROM argument_xrefs WHERE src_rowid=def.rowid),\n"
501 "\tEXISTS (SELECT rowid FROM initializer_xrefs WHERE dst_rowid=def.rowid),\n"
502 "\tEXISTS (SELECT rowid FROM initializer_xrefs WHERE src_rowid=def.rowid)\n"
503 "FROM def ORDER BY def.rowid;"
504 }
505};
506
507//////////////////////////////////////////////////////
508struct SqlStmt {
509 const char *query = nullptr;
510 sqlite3_stmt *stmt = nullptr;
511 sqlite3 *db = nullptr;
512};
513//////////////////////////////////////////////////////
514/* If you add a new statement below, make sure to add it to
515 prepareStatements(). If sqlite3 is segfaulting (especially in
516 sqlite3_clear_bindings()), using an un-prepared statement may
517 be the cause. */
519 "INSERT INTO meta "
520 "( doxygen_version, schema_version, generated_at, generated_on, project_name, project_number, project_brief )"
521 "VALUES "
522 "(:doxygen_version,:schema_version,:generated_at,:generated_on,:project_name,:project_number,:project_brief )"
523 ,nullptr
524};
525//////////////////////////////////////////////////////
527 "INSERT INTO includes "
528 "( local, src_id, dst_id ) "
529 "VALUES "
530 "(:local,:src_id,:dst_id )"
531 ,nullptr
532};
534 "SELECT COUNT(*) FROM includes WHERE "
535 "local=:local AND src_id=:src_id AND dst_id=:dst_id"
536 ,nullptr
537};
538//////////////////////////////////////////////////////
540 "INSERT INTO contains "
541 "( inner_rowid, outer_rowid )"
542 "VALUES "
543 "(:inner_rowid,:outer_rowid )"
544 ,nullptr
545};
546//////////////////////////////////////////////////////
548 "SELECT rowid FROM path WHERE name=:name"
549 ,nullptr
550};
552 "INSERT INTO path "
553 "( type, local, found, name )"
554 "VALUES "
555 "(:type,:local,:found,:name )"
556 ,nullptr
557};
558//////////////////////////////////////////////////////
560 "SELECT rowid FROM refid WHERE refid=:refid"
561 ,nullptr
562};
564 "INSERT INTO refid "
565 "( refid )"
566 "VALUES "
567 "(:refid )"
568 ,nullptr
569};
570//////////////////////////////////////////////////////
572 "INSERT INTO xrefs "
573 "( src_rowid, dst_rowid, context )"
574 "VALUES "
575 "(:src_rowid,:dst_rowid,:context )"
576 ,nullptr
577};//////////////////////////////////////////////////////
579 "INSERT INTO reimplements "
580 "( memberdef_rowid, reimplemented_rowid )"
581 "VALUES "
582 "(:memberdef_rowid,:reimplemented_rowid )"
583 ,nullptr
584};
585//////////////////////////////////////////////////////
587 "SELECT EXISTS (SELECT * FROM memberdef WHERE rowid = :rowid)"
588 ,nullptr
589};
590
592 "SELECT EXISTS ("
593 "SELECT * FROM memberdef WHERE "
594 "rowid = :rowid AND inline != 2 AND inline != :new_inline"
595 ")"
596 ,nullptr
597};
598
600 "INSERT INTO memberdef "
601 "("
602 "rowid,"
603 "name,"
604 "definition,"
605 "type,"
606 "argsstring,"
607 "scope,"
608 "initializer,"
609 "bitfield,"
610 "read,"
611 "write,"
612 "prot,"
613 "static,"
614 "extern,"
615 "const,"
616 "explicit,"
617 "inline,"
618 "final,"
619 "sealed,"
620 "new,"
621 "optional,"
622 "required,"
623 "volatile,"
624 "virt,"
625 "mutable,"
626 "initonly,"
627 "attribute,"
628 "property,"
629 "readonly,"
630 "bound,"
631 "constrained,"
632 "transient,"
633 "maybevoid,"
634 "maybedefault,"
635 "maybeambiguous,"
636 "readable,"
637 "writable,"
638 "gettable,"
639 "protectedsettable,"
640 "protectedgettable,"
641 "settable,"
642 "privatesettable,"
643 "privategettable,"
644 "accessor,"
645 "addable,"
646 "removable,"
647 "raisable,"
648 "kind,"
649 "bodystart,"
650 "bodyend,"
651 "bodyfile_id,"
652 "file_id,"
653 "line,"
654 "column,"
655 "detaileddescription,"
656 "briefdescription,"
657 "inbodydescription"
658 ")"
659 "VALUES "
660 "("
661 ":rowid,"
662 ":name,"
663 ":definition,"
664 ":type,"
665 ":argsstring,"
666 ":scope,"
667 ":initializer,"
668 ":bitfield,"
669 ":read,"
670 ":write,"
671 ":prot,"
672 ":static,"
673 ":extern,"
674 ":const,"
675 ":explicit,"
676 ":inline,"
677 ":final,"
678 ":sealed,"
679 ":new,"
680 ":optional,"
681 ":required,"
682 ":volatile,"
683 ":virt,"
684 ":mutable,"
685 ":initonly,"
686 ":attribute,"
687 ":property,"
688 ":readonly,"
689 ":bound,"
690 ":constrained,"
691 ":transient,"
692 ":maybevoid,"
693 ":maybedefault,"
694 ":maybeambiguous,"
695 ":readable,"
696 ":writable,"
697 ":gettable,"
698 ":protectedsettable,"
699 ":protectedgettable,"
700 ":settable,"
701 ":privatesettable,"
702 ":privategettable,"
703 ":accessor,"
704 ":addable,"
705 ":removable,"
706 ":raisable,"
707 ":kind,"
708 ":bodystart,"
709 ":bodyend,"
710 ":bodyfile_id,"
711 ":file_id,"
712 ":line,"
713 ":column,"
714 ":detaileddescription,"
715 ":briefdescription,"
716 ":inbodydescription"
717 ")"
718 ,nullptr
719};
720/*
721We have a slightly different need than the XML here. The XML can have two
722memberdef nodes with the same refid to document the declaration and the
723definition. This doesn't play very nice with a referential model. It isn't a
724big issue if only one is documented, but in case both are, we'll fall back on
725this kludge to combine them in a single row...
726*/
728 "UPDATE memberdef SET "
729 "inline = :inline,"
730 "file_id = :file_id,"
731 "line = :line,"
732 "column = :column,"
733 "detaileddescription = 'Declaration: ' || :detaileddescription || 'Definition: ' || detaileddescription,"
734 "briefdescription = 'Declaration: ' || :briefdescription || 'Definition: ' || briefdescription,"
735 "inbodydescription = 'Declaration: ' || :inbodydescription || 'Definition: ' || inbodydescription "
736 "WHERE rowid = :rowid"
737 ,nullptr
738};
740 "UPDATE memberdef SET "
741 "inline = :inline,"
742 "bodystart = :bodystart,"
743 "bodyend = :bodyend,"
744 "bodyfile_id = :bodyfile_id,"
745 "detaileddescription = 'Declaration: ' || detaileddescription || 'Definition: ' || :detaileddescription,"
746 "briefdescription = 'Declaration: ' || briefdescription || 'Definition: ' || :briefdescription,"
747 "inbodydescription = 'Declaration: ' || inbodydescription || 'Definition: ' || :inbodydescription "
748 "WHERE rowid = :rowid"
749 ,nullptr
750};
751//////////////////////////////////////////////////////
753 "INSERT INTO member "
754 "( scope_rowid, memberdef_rowid, prot, virt ) "
755 "VALUES "
756 "(:scope_rowid,:memberdef_rowid,:prot,:virt )"
757 ,nullptr
758};
759//////////////////////////////////////////////////////
761 "INSERT INTO compounddef "
762 "("
763 "rowid,"
764 "name,"
765 "title,"
766 "kind,"
767 "prot,"
768 "file_id,"
769 "line,"
770 "column,"
771 "header_id,"
772 "briefdescription,"
773 "detaileddescription"
774 ")"
775 "VALUES "
776 "("
777 ":rowid,"
778 ":name,"
779 ":title,"
780 ":kind,"
781 ":prot,"
782 ":file_id,"
783 ":line,"
784 ":column,"
785 ":header_id,"
786 ":briefdescription,"
787 ":detaileddescription"
788 ")"
789 ,nullptr
790};
792 "SELECT EXISTS ("
793 "SELECT * FROM compounddef WHERE rowid = :rowid"
794 ")"
795 ,nullptr
796};
797//////////////////////////////////////////////////////
799 "INSERT INTO compoundref "
800 "( base_rowid, derived_rowid, prot, virt ) "
801 "VALUES "
802 "(:base_rowid,:derived_rowid,:prot,:virt )"
803 ,nullptr
804};
805//////////////////////////////////////////////////////
807 "SELECT rowid FROM param WHERE "
808 "(attributes IS NULL OR attributes=:attributes) AND "
809 "(type IS NULL OR type=:type) AND "
810 "(declname IS NULL OR declname=:declname) AND "
811 "(defname IS NULL OR defname=:defname) AND "
812 "(array IS NULL OR array=:array) AND "
813 "(defval IS NULL OR defval=:defval) AND "
814 "(briefdescription IS NULL OR briefdescription=:briefdescription)"
815 ,nullptr
816};
818 "INSERT INTO param "
819 "( attributes, type, declname, defname, array, defval, briefdescription ) "
820 "VALUES "
821 "(:attributes,:type,:declname,:defname,:array,:defval,:briefdescription)"
822 ,nullptr
823};
824//////////////////////////////////////////////////////
826 "INSERT INTO memberdef_param "
827 "( memberdef_id, param_id)"
828 "VALUES "
829 "(:memberdef_id,:param_id)"
830 ,nullptr
831};
832
834{
835 public:
837 void writeString(std::string_view /*s*/,bool /*keepSpaces*/) const override
838 {
839 }
840 void writeBreak(int) const override
841 {
842 DBG_CTX(("writeBreak\n"));
843 }
844 void writeLink(const QCString & /*extRef*/,const QCString &file,
845 const QCString &anchor,std::string_view /*text*/
846 ) const override
847 {
848 std::string rs = file.str();
849 if (!anchor.isEmpty())
850 {
851 rs+="_1";
852 rs+=anchor.str();
853 }
854 m_list.push_back(rs);
855 }
856 private:
858 // the list is filled by linkifyText and consumed by the caller
859};
860
861
862static bool bindTextParameter(SqlStmt &s,const char *name,const QCString &value)
863{
864 int idx = sqlite3_bind_parameter_index(s.stmt, name);
865 if (idx==0) {
866 err("sqlite3_bind_parameter_index({})[{}] failed: {}\n", name, s.query, sqlite3_errmsg(s.db));
867 return false;
868 }
869 int rv = sqlite3_bind_text(s.stmt, idx, value.data(), -1, SQLITE_TRANSIENT);
870 if (rv!=SQLITE_OK) {
871 err("sqlite3_bind_text({})[{}] failed: {}\n", name, s.query, sqlite3_errmsg(s.db));
872 return false;
873 }
874 return true;
875}
876
877static bool bindIntParameter(SqlStmt &s,const char *name,int value)
878{
879 int idx = sqlite3_bind_parameter_index(s.stmt, name);
880 if (idx==0) {
881 err("sqlite3_bind_parameter_index({})[{}] failed to find column: {}\n", name, s.query, sqlite3_errmsg(s.db));
882 return false;
883 }
884 int rv = sqlite3_bind_int(s.stmt, idx, value);
885 if (rv!=SQLITE_OK) {
886 err("sqlite3_bind_int({})[{}] failed: {}\n", name, s.query, sqlite3_errmsg(s.db));
887 return false;
888 }
889 return true;
890}
891
892static int step(SqlStmt &s,bool getRowId=FALSE, bool select=FALSE)
893{
894 int rowid=-1;
895 int rc = sqlite3_step(s.stmt);
896 if (rc!=SQLITE_DONE && rc!=SQLITE_ROW)
897 {
898 DBG_CTX(("sqlite3_step: %s (rc: %d)\n", sqlite3_errmsg(s.db), rc));
899 sqlite3_reset(s.stmt);
900 sqlite3_clear_bindings(s.stmt);
901 return -1;
902 }
903 if (getRowId && select) rowid = sqlite3_column_int(s.stmt, 0); // works on selects, doesn't on inserts
904 if (getRowId && !select) rowid = static_cast<int>(sqlite3_last_insert_rowid(s.db)); //works on inserts, doesn't on selects
905 sqlite3_reset(s.stmt);
906 sqlite3_clear_bindings(s.stmt); // XXX When should this really be called
907 return rowid;
908}
909
910static int insertPath(QCString name, bool local=TRUE, bool found=TRUE, int type=1)
911{
912 int rowid=-1;
913 if (name==nullptr) return rowid;
914
915 name = stripFromPath(name);
916
917 bindTextParameter(path_select,":name",name.data());
918 rowid=step(path_select,TRUE,TRUE);
919 if (rowid==0)
920 {
921 bindTextParameter(path_insert,":name",name.data());
922 bindIntParameter(path_insert,":type",type);
923 bindIntParameter(path_insert,":local",local?1:0);
924 bindIntParameter(path_insert,":found",found?1:0);
925 rowid=step(path_insert,TRUE);
926 }
927 return rowid;
928}
929
930static void recordMetadata()
931{
932 bindTextParameter(meta_insert,":doxygen_version",getFullVersion());
933 bindTextParameter(meta_insert,":schema_version","0.2.1"); //TODO: this should be a constant somewhere; not sure where
936 bindTextParameter(meta_insert,":project_name",Config_getString(PROJECT_NAME));
937 bindTextParameter(meta_insert,":project_number",Config_getString(PROJECT_NUMBER));
938 bindTextParameter(meta_insert,":project_brief",Config_getString(PROJECT_BRIEF));
940}
941
942struct Refid {
943 int rowid;
946};
947
949{
950 Refid ret;
951 ret.rowid=-1;
952 ret.refid=refid;
953 ret.created = FALSE;
954 if (refid.isEmpty()) return ret;
955
958 if (ret.rowid==0)
959 {
962 ret.created = TRUE;
963 }
964
965 return ret;
966}
967
968static bool memberdefExists(struct Refid refid)
969{
971 int test = step(memberdef_exists,TRUE,TRUE);
972 return test ? true : false;
973}
974
975static bool memberdefIncomplete(struct Refid refid, const MemberDef* md)
976{
980 return test ? true : false;
981}
982
983static bool compounddefExists(struct Refid refid)
984{
986 int test = step(compounddef_exists,TRUE,TRUE);
987 return test ? true : false;
988}
989
990static bool insertMemberReference(struct Refid src_refid, struct Refid dst_refid, const char *context)
991{
992 if (src_refid.rowid==-1||dst_refid.rowid==-1)
993 return false;
994
995 if (
996 !bindIntParameter(xrefs_insert,":src_rowid",src_refid.rowid) ||
997 !bindIntParameter(xrefs_insert,":dst_rowid",dst_refid.rowid)
998 )
999 {
1000 return false;
1001 }
1002 else
1003 {
1004 bindTextParameter(xrefs_insert,":context",context);
1005 }
1006
1008 return true;
1009}
1010
1011static void insertMemberReference(const MemberDef *src, const MemberDef *dst, const char *context)
1012{
1013 QCString qdst_refid = dst->getOutputFileBase() + "_1" + dst->anchor();
1014 QCString qsrc_refid = src->getOutputFileBase() + "_1" + src->anchor();
1015
1016 struct Refid src_refid = insertRefid(qsrc_refid);
1017 struct Refid dst_refid = insertRefid(qdst_refid);
1018 insertMemberReference(src_refid,dst_refid,context);
1019}
1020
1021static void insertMemberFunctionParams(int memberdef_id, const MemberDef *md, const Definition *def)
1022{
1023 const ArgumentList &declAl = md->declArgumentList();
1024 const ArgumentList &defAl = md->argumentList();
1025 if (declAl.size()>0)
1026 {
1027 auto defIt = defAl.begin();
1028 for (const Argument &a : declAl)
1029 {
1030 //const Argument *defArg = defAli.current();
1031 const Argument *defArg = nullptr;
1032 if (defIt!=defAl.end())
1033 {
1034 defArg = &(*defIt);
1035 ++defIt;
1036 }
1037
1038 if (!a.attrib.isEmpty())
1039 {
1040 bindTextParameter(param_select,":attributes",a.attrib);
1041 bindTextParameter(param_insert,":attributes",a.attrib);
1042 }
1043 if (!a.type.isEmpty())
1044 {
1045 StringVector list;
1046 linkifyText(TextGeneratorSqlite3Impl(list),def,md->getBodyDef(),md,a.type);
1047
1048 for (const auto &s : list)
1049 {
1050 QCString qsrc_refid = md->getOutputFileBase() + "_1" + md->anchor();
1051 struct Refid src_refid = insertRefid(qsrc_refid);
1052 struct Refid dst_refid = insertRefid(s.c_str());
1053 insertMemberReference(src_refid,dst_refid, "argument");
1054 }
1055 bindTextParameter(param_select,":type",a.type);
1056 bindTextParameter(param_insert,":type",a.type);
1057 }
1058 if (!a.name.isEmpty())
1059 {
1060 bindTextParameter(param_select,":declname",a.name);
1061 bindTextParameter(param_insert,":declname",a.name);
1062 }
1063 if (defArg && !defArg->name.isEmpty() && defArg->name!=a.name)
1064 {
1065 bindTextParameter(param_select,":defname",defArg->name);
1066 bindTextParameter(param_insert,":defname",defArg->name);
1067 }
1068 if (!a.array.isEmpty())
1069 {
1070 bindTextParameter(param_select,":array",a.array);
1071 bindTextParameter(param_insert,":array",a.array);
1072 }
1073 if (!a.defval.isEmpty())
1074 {
1075 StringVector list;
1076 linkifyText(TextGeneratorSqlite3Impl(list),def,md->getBodyDef(),md,a.defval);
1077 bindTextParameter(param_select,":defval",a.defval);
1078 bindTextParameter(param_insert,":defval",a.defval);
1079 }
1080
1081 int param_id=step(param_select,TRUE,TRUE);
1082 if (param_id==0) {
1083 param_id=step(param_insert,TRUE);
1084 }
1085 if (param_id==-1) {
1086 DBG_CTX(("error INSERT params failed\n"));
1087 continue;
1088 }
1089
1090 bindIntParameter(memberdef_param_insert,":memberdef_id",memberdef_id);
1091 bindIntParameter(memberdef_param_insert,":param_id",param_id);
1093 }
1094 }
1095}
1096
1097static void insertMemberDefineParams(int memberdef_id,const MemberDef *md, const Definition *def)
1098{
1099 if (md->argumentList().empty()) // special case for "foo()" to
1100 // distinguish it from "foo".
1101 {
1102 DBG_CTX(("no params\n"));
1103 }
1104 else
1105 {
1106 for (const Argument &a : md->argumentList())
1107 {
1108 bindTextParameter(param_insert,":defname",a.type);
1109 int param_id=step(param_insert,TRUE);
1110 if (param_id==-1) {
1111 continue;
1112 }
1113
1114 bindIntParameter(memberdef_param_insert,":memberdef_id",memberdef_id);
1115 bindIntParameter(memberdef_param_insert,":param_id",param_id);
1117 }
1118 }
1119}
1120
1121static void associateMember(const MemberDef *md, struct Refid member_refid, struct Refid scope_refid)
1122{
1123 // TODO: skip EnumValue only to guard against recording refids and member records
1124 // for enumvalues until we can support documenting them as entities.
1125 if (md->memberType()==MemberType::EnumValue) return;
1126 if (!md->isAnonymous()) // skip anonymous members
1127 {
1128 bindIntParameter(member_insert, ":scope_rowid", scope_refid.rowid);
1129 bindIntParameter(member_insert, ":memberdef_rowid", member_refid.rowid);
1130
1131 bindIntParameter(member_insert, ":prot", static_cast<int>(md->protection()));
1132 bindIntParameter(member_insert, ":virt", static_cast<int>(md->virtualness()));
1134 }
1135}
1136
1137static void stripQualifiers(QCString &typeStr)
1138{
1139 bool done=FALSE;
1140 while (!done)
1141 {
1142 if (typeStr.stripPrefix("static "));
1143 else if (typeStr.stripPrefix("virtual "));
1144 else if (typeStr=="virtual") typeStr="";
1145 else done=TRUE;
1146 }
1147}
1148
1149static int prepareStatement(sqlite3 *db, SqlStmt &s)
1150{
1151 int rc = sqlite3_prepare_v2(db,s.query,-1,&s.stmt,nullptr);
1152 if (rc!=SQLITE_OK)
1153 {
1154 err("prepare failed for:\n {}\n {}\n", s.query, sqlite3_errmsg(db));
1155 s.db = nullptr;
1156 return -1;
1157 }
1158 s.db = db;
1159 return rc;
1160}
1161
1162static int prepareStatements(sqlite3 *db)
1163{
1164 if (
1165 -1==prepareStatement(db, meta_insert) ||
1172 -1==prepareStatement(db, path_insert) ||
1173 -1==prepareStatement(db, path_select) ||
1174 -1==prepareStatement(db, refid_insert) ||
1175 -1==prepareStatement(db, refid_select) ||
1176 -1==prepareStatement(db, incl_insert)||
1177 -1==prepareStatement(db, incl_select)||
1178 -1==prepareStatement(db, param_insert) ||
1179 -1==prepareStatement(db, param_select) ||
1180 -1==prepareStatement(db, xrefs_insert) ||
1187 )
1188 {
1189 return -1;
1190 }
1191 return 0;
1192}
1193
1194static void beginTransaction(sqlite3 *db)
1195{
1196 char * sErrMsg = nullptr;
1197 sqlite3_exec(db, "BEGIN TRANSACTION", nullptr, nullptr, &sErrMsg);
1198}
1199
1200static void endTransaction(sqlite3 *db)
1201{
1202 char * sErrMsg = nullptr;
1203 sqlite3_exec(db, "END TRANSACTION", nullptr, nullptr, &sErrMsg);
1204}
1205
1206static void pragmaTuning(sqlite3 *db)
1207{
1208 char * sErrMsg = nullptr;
1209 sqlite3_exec(db, "PRAGMA synchronous = OFF", nullptr, nullptr, &sErrMsg);
1210 sqlite3_exec(db, "PRAGMA journal_mode = MEMORY", nullptr, nullptr, &sErrMsg);
1211 sqlite3_exec(db, "PRAGMA temp_store = MEMORY;", nullptr, nullptr, &sErrMsg);
1212}
1213
1214static int initializeTables(sqlite3* db)
1215{
1216 msg("Initializing DB schema (tables)...\n");
1217 for (unsigned int k = 0; k < sizeof(table_schema) / sizeof(table_schema[0]); k++)
1218 {
1219 const char *q = table_schema[k][1];
1220 char *errmsg = nullptr;
1221 int rc = sqlite3_exec(db, q, nullptr, nullptr, &errmsg);
1222 if (rc != SQLITE_OK)
1223 {
1224 err("failed to execute query: {}\n\t{}\n", q, errmsg);
1225 return -1;
1226 }
1227 }
1228 return 0;
1229}
1230
1231static int initializeViews(sqlite3* db)
1232{
1233 msg("Initializing DB schema (views)...\n");
1234 for (unsigned int k = 0; k < sizeof(view_schema) / sizeof(view_schema[0]); k++)
1235 {
1236 const char *q = view_schema[k][1];
1237 char *errmsg = nullptr;
1238 int rc = sqlite3_exec(db, q, nullptr, nullptr, &errmsg);
1239 if (rc != SQLITE_OK)
1240 {
1241 err("failed to execute query: {}\n\t{}\n", q, errmsg);
1242 return -1;
1243 }
1244 }
1245 return 0;
1246}
1247
1248////////////////////////////////////////////
1249/* TODO:
1250I collapsed all innerX tables into 'contains', which raises the prospect that
1251all of these very similar writeInnerX funcs could be refactored into a one,
1252or a small set of common parts.
1253
1254I think the hurdles are:
1255- picking a first argument that every call location can pass
1256- which yields a consistent iterator
1257- accommodates PageDef's slightly different rules for generating the
1258 inner_refid (unless I'm missing a method that would uniformly return
1259 the correct refid for all types).
1260*/
1261static void writeInnerClasses(const ClassLinkedRefMap &cl, struct Refid outer_refid)
1262{
1263 for (const auto &cd : cl)
1264 {
1265 if (!cd->isHidden() && !cd->isAnonymous())
1266 {
1267 struct Refid inner_refid = insertRefid(cd->getOutputFileBase());
1268
1269 bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid);
1270 bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid);
1272 }
1273 }
1274}
1275
1276static void writeInnerConcepts(const ConceptLinkedRefMap &cl, struct Refid outer_refid)
1277{
1278 for (const auto &cd : cl)
1279 {
1280 struct Refid inner_refid = insertRefid(cd->getOutputFileBase());
1281
1282 bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid);
1283 bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid);
1285 }
1286}
1287
1288static void writeInnerModules(const ModuleLinkedRefMap &ml, struct Refid outer_refid)
1289{
1290 for (const auto &mod : ml)
1291 {
1292 struct Refid inner_refid = insertRefid(mod->getOutputFileBase());
1293
1294 bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid);
1295 bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid);
1297 }
1298}
1299
1300
1301static void writeInnerPages(const PageLinkedRefMap &pl, struct Refid outer_refid)
1302{
1303 for (const auto &pd : pl)
1304 {
1305 struct Refid inner_refid = insertRefid(
1306 pd->getGroupDef() ? pd->getOutputFileBase()+"_"+pd->name() : pd->getOutputFileBase()
1307 );
1308
1309 bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid);
1310 bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid);
1312 }
1313}
1314
1315static void writeInnerGroups(const GroupList &gl, struct Refid outer_refid)
1316{
1317 for (const auto &sgd : gl)
1318 {
1319 struct Refid inner_refid = insertRefid(sgd->getOutputFileBase());
1320
1321 bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid);
1322 bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid);
1324 }
1325}
1326
1327static void writeInnerFiles(const FileList &fl, struct Refid outer_refid)
1328{
1329 for (const auto &fd: fl)
1330 {
1331 struct Refid inner_refid = insertRefid(fd->getOutputFileBase());
1332
1333 bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid);
1334 bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid);
1336 }
1337}
1338
1339static void writeInnerDirs(const DirList &dl, struct Refid outer_refid)
1340{
1341 for (const auto subdir : dl)
1342 {
1343 struct Refid inner_refid = insertRefid(subdir->getOutputFileBase());
1344
1345 bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid);
1346 bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid);
1348 }
1349}
1350
1351static void writeInnerNamespaces(const NamespaceLinkedRefMap &nl, struct Refid outer_refid)
1352{
1353 for (const auto &nd : nl)
1354 {
1355 if (!nd->isHidden() && !nd->isAnonymous())
1356 {
1357 struct Refid inner_refid = insertRefid(nd->getOutputFileBase());
1358
1359 bindIntParameter(contains_insert,":inner_rowid",inner_refid.rowid);
1360 bindIntParameter(contains_insert,":outer_rowid",outer_refid.rowid);
1362 }
1363 }
1364}
1365
1366
1368 const Definition * scope,
1369 const FileDef * fileScope)
1370{
1371 for (const Argument &a : al)
1372 {
1373 if (!a.type.isEmpty())
1374 {
1375//#warning linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a.type);
1376 bindTextParameter(param_select,":type",a.type);
1377 bindTextParameter(param_insert,":type",a.type);
1378 }
1379 if (!a.name.isEmpty())
1380 {
1381 bindTextParameter(param_select,":declname",a.name);
1382 bindTextParameter(param_insert,":declname",a.name);
1383 bindTextParameter(param_select,":defname",a.name);
1384 bindTextParameter(param_insert,":defname",a.name);
1385 }
1386 if (!a.defval.isEmpty())
1387 {
1388//#warning linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a.defval);
1389 bindTextParameter(param_select,":defval",a.defval);
1390 bindTextParameter(param_insert,":defval",a.defval);
1391 }
1392 if (!step(param_select,TRUE,TRUE))
1394 }
1395}
1396
1401
1402static void writeTemplateList(const ClassDef *cd)
1403{
1405}
1406
1407static void writeTemplateList(const ConceptDef *cd)
1408{
1410}
1411
1413 const Definition *def,
1414 const QCString &doc,
1415 const QCString &fileName,
1416 int lineNr)
1417{
1418 if (doc.isEmpty()) return "";
1419
1420 TextStream t;
1421 auto parser { createDocParser() };
1422 auto ast { validatingParseDoc(
1423 *parser.get(),
1424 fileName,
1425 lineNr,
1426 scope,
1427 toMemberDef(def),
1428 doc,
1429 FALSE,
1430 FALSE,
1431 QCString(),
1432 FALSE,
1433 FALSE)
1434 };
1435 auto astImpl = dynamic_cast<const DocNodeAST*>(ast.get());
1436 if (astImpl)
1437 {
1438 OutputCodeList xmlCodeList;
1439 xmlCodeList.add<XMLCodeGenerator>(&t);
1440 // create a parse tree visitor for XML
1441 XmlDocVisitor visitor(t,xmlCodeList,
1442 scope ? scope->getDefFileExtension() : QCString(""));
1443 std::visit(visitor,astImpl->root);
1444 }
1445 return convertCharEntitiesToUTF8(t.str().c_str());
1446}
1447
1448static void getSQLDesc(SqlStmt &s,const char *col,const QCString &value,const Definition *def)
1449{
1451 s,
1452 col,
1454 def->getOuterScope(),
1455 def,
1456 value,
1457 def->docFile(),
1458 def->docLine()
1459 )
1460 );
1461}
1462
1463static void getSQLDescCompound(SqlStmt &s,const char *col,const QCString &value,const Definition *def)
1464{
1466 s,
1467 col,
1469 def,
1470 def,
1471 value,
1472 def->docFile(),
1473 def->docLine()
1474 )
1475 );
1476}
1477////////////////////////////////////////////
1478
1479/* (updated Sep 01 2018)
1480DoxMemberKind and DoxCompoundKind (compound.xsd) gave me some
1481faulty assumptions about "kind" strings, so I compiled a reference
1482
1483The XML schema claims:
1484 DoxMemberKind: (14)
1485 dcop define enum event friend function interface property prototype
1486 service signal slot typedef variable
1487
1488 DoxCompoundKind: (17)
1489 category class dir example exception file group interface module
1490 namespace page protocol service singleton struct type union
1491
1492Member kind comes from MemberDef::memberTypeName()
1493 types.h defines 14 MemberType::*s
1494 _DCOP _Define _Enumeration _EnumValue _Event _Friend _Function _Interface
1495 _Property _Service _Signal _Slot _Typedef _Variable
1496 - xml doesn't include enumvalue here
1497 (but renders enumvalue as) a sub-node of memberdef/templateparamlist
1498 - xml includes 'prototype' that is unlisted here
1499 vestigial? commented out in docsets.cpp and perlmodgen.cpp
1500 MemberDef::memberTypeName() can return 15 strings:
1501 (sorted by MemberType to match above; quoted because whitespace...)
1502 "dcop" "macro definition" "enumeration" "enumvalue" "event" "friend"
1503 "function" "interface" "property" "service" "signal" "slot" "typedef"
1504 "variable"
1505
1506 Above describes potential values for memberdef.kind
1507
1508Compound kind is more complex. *Def::compoundTypeString()
1509 ClassDef kind comes from ::compoundTypeString()
1510 classdef.h defines 9 compound types
1511 Category Class Exception Interface Protocol Service Singleton Struct Union
1512 But ClassDef::compoundTypeString() "could" return 13 strings
1513 - default "unknown" shouldn't actually return
1514 - other 12 can vary by source language; see method for specifics
1515 category class enum exception interface module protocol service
1516 singleton struct type union
1517
1518 DirDef, FileDef, GroupDef have no method to return a string
1519 tagfile/outputs hard-code kind to 'dir' 'file' or 'group'
1520
1521 NamespaceDef kind comes from ::compoundTypeString()
1522 NamespaceDef::compoundTypeString() "could" return 6 strings
1523 - default empty ("") string
1524 - other 5 differ by source language
1525 constants library module namespace package
1526
1527 PageDef also has no method to return a string
1528 - some locations hard-code the kind to 'page'
1529 - others conditionally output 'page' or 'example'
1530
1531 All together, that's 23 potential strings (21 excl "" and unknown)
1532 "" category class constants dir enum example exception file group
1533 interface library module namespace package page protocol service singleton
1534 struct type union unknown
1535
1536 Above describes potential values for compounddef.kind
1537
1538For reference, there are 35 potential values of def.kind (33 excl "" and unknown):
1539 "" "category" "class" "constants" "dcop" "dir" "enum" "enumeration"
1540 "enumvalue" "event" "example" "exception" "file" "friend" "function" "group"
1541 "interface" "library" "macro definition" "module" "namespace" "package"
1542 "page" "property" "protocol" "service" "signal" "singleton" "slot" "struct"
1543 "type" "typedef" "union" "unknown" "variable"
1544
1545This is relevant because the 'def' view generalizes memberdef and compounddef,
1546and two member+compound kind strings (interface and service) overlap.
1547
1548I have no grasp of whether a real user docset would include one or more
1549member and compound using the interface or service kind.
1550*/
1551
1552//////////////////////////////////////////////////////////////////////////////
1553static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_refid, const Definition *def)
1554{
1555 // + declaration/definition arg lists
1556 // + reimplements
1557 // + reimplementedBy
1558 // - exceptions
1559 // + const/volatile specifiers
1560 // - examples
1561 // + source definition
1562 // + source references
1563 // + source referenced by
1564 // - body code
1565 // + template arguments
1566 // (templateArguments(), definitionTemplateParameterLists())
1567 // - call graph
1568
1569 // enum values are written as part of the enum
1570 if (md->memberType()==MemberType::EnumValue) return;
1571 if (md->isHidden()) return;
1572
1573 QCString memType;
1574
1575 // memberdef
1576 QCString qrefid = md->getOutputFileBase() + "_1" + md->anchor();
1577 struct Refid refid = insertRefid(qrefid);
1578
1579 associateMember(md, refid, scope_refid);
1580
1581 // compacting duplicate defs
1582 if(!refid.created && memberdefExists(refid) && memberdefIncomplete(refid, md))
1583 {
1584 /*
1585 For performance, ideal to skip a member we've already added.
1586 Unfortunately, we can have two memberdefs with the same refid documenting
1587 the declaration and definition. memberdefIncomplete() uses the 'inline'
1588 value to figure this out. Once we get to this point, we should *only* be
1589 seeing the *other* type of def/decl, so we'll set inline to a new value (2),
1590 indicating that this entry covers both inline types.
1591 */
1592 struct SqlStmt memberdef_update;
1593
1594 // definitions have bodyfile/start/end
1595 if (md->getStartBodyLine()!=-1)
1596 {
1597 memberdef_update = memberdef_update_def;
1598 int bodyfile_id = insertPath(md->getBodyDef()->absFilePath(),!md->getBodyDef()->isReference());
1599 if (bodyfile_id == -1)
1600 {
1601 sqlite3_clear_bindings(memberdef_update.stmt);
1602 }
1603 else
1604 {
1605 bindIntParameter(memberdef_update,":bodyfile_id",bodyfile_id);
1606 bindIntParameter(memberdef_update,":bodystart",md->getStartBodyLine());
1607 bindIntParameter(memberdef_update,":bodyend",md->getEndBodyLine());
1608 }
1609 }
1610 // declarations don't
1611 else
1612 {
1613 memberdef_update = memberdef_update_decl;
1614 if (md->getDefLine() != -1)
1615 {
1616 int file_id = insertPath(md->getDefFileName(),!md->isReference());
1617 if (file_id!=-1)
1618 {
1619 bindIntParameter(memberdef_update,":file_id",file_id);
1620 bindIntParameter(memberdef_update,":line",md->getDefLine());
1621 bindIntParameter(memberdef_update,":column",md->getDefColumn());
1622 }
1623 }
1624 }
1625
1626 bindIntParameter(memberdef_update, ":rowid", refid.rowid);
1627 // value 2 indicates we've seen "both" inline types.
1628 bindIntParameter(memberdef_update,":inline", 2);
1629
1630 /* in case both are used, append/prepend descriptions */
1631 getSQLDesc(memberdef_update,":briefdescription",md->briefDescription(),md);
1632 getSQLDesc(memberdef_update,":detaileddescription",md->documentation(),md);
1633 getSQLDesc(memberdef_update,":inbodydescription",md->inbodyDocumentation(),md);
1634
1635 step(memberdef_update,TRUE);
1636
1637 // don't think we need to repeat params; should have from first encounter
1638
1639 // + source references
1640 // The cross-references in initializers only work when both the src and dst
1641 // are defined.
1642 auto refList = md->getReferencesMembers();
1643 for (const auto &rmd : refList)
1644 {
1645 insertMemberReference(md,rmd, "inline");
1646 }
1647 // + source referenced by
1648 auto refByList = md->getReferencedByMembers();
1649 for (const auto &rmd : refByList)
1650 {
1651 insertMemberReference(rmd,md, "inline");
1652 }
1653 return;
1654 }
1655
1656 bindIntParameter(memberdef_insert,":rowid", refid.rowid);
1658 bindIntParameter(memberdef_insert,":prot",static_cast<int>(md->protection()));
1659
1662
1663 bool isFunc=FALSE;
1664 switch (md->memberType())
1665 {
1666 case MemberType::Function: // fall through
1667 case MemberType::Signal: // fall through
1668 case MemberType::Friend: // fall through
1669 case MemberType::DCOP: // fall through
1670 case MemberType::Slot:
1671 isFunc=TRUE;
1672 break;
1673 default:
1674 break;
1675 }
1676
1677 if (isFunc)
1678 {
1679 const ArgumentList &al = md->argumentList();
1682 bindIntParameter(memberdef_insert,":explicit",md->isExplicit());
1687 bindIntParameter(memberdef_insert,":optional",md->isOptional());
1688 bindIntParameter(memberdef_insert,":required",md->isRequired());
1689
1690 bindIntParameter(memberdef_insert,":virt",static_cast<int>(md->virtualness()));
1691 }
1692
1693 if (md->memberType() == MemberType::Variable)
1694 {
1696 bindIntParameter(memberdef_insert,":initonly",md->isInitonly());
1697 bindIntParameter(memberdef_insert,":attribute",md->isAttribute());
1698 bindIntParameter(memberdef_insert,":property",md->isProperty());
1699 bindIntParameter(memberdef_insert,":readonly",md->isReadonly());
1701 bindIntParameter(memberdef_insert,":removable",md->isRemovable());
1702 bindIntParameter(memberdef_insert,":constrained",md->isConstrained());
1703 bindIntParameter(memberdef_insert,":transient",md->isTransient());
1704 bindIntParameter(memberdef_insert,":maybevoid",md->isMaybeVoid());
1705 bindIntParameter(memberdef_insert,":maybedefault",md->isMaybeDefault());
1706 bindIntParameter(memberdef_insert,":maybeambiguous",md->isMaybeAmbiguous());
1707 if (!md->bitfieldString().isEmpty())
1708 {
1709 QCString bitfield = md->bitfieldString();
1710 if (bitfield.at(0)==':') bitfield=bitfield.mid(1);
1711 bindTextParameter(memberdef_insert,":bitfield",bitfield.stripWhiteSpace());
1712 }
1713 }
1714 else if (md->memberType() == MemberType::Property)
1715 {
1716 bindIntParameter(memberdef_insert,":readable",md->isReadable());
1717 bindIntParameter(memberdef_insert,":writable",md->isWritable());
1718 bindIntParameter(memberdef_insert,":gettable",md->isGettable());
1719 bindIntParameter(memberdef_insert,":privategettable",md->isPrivateGettable());
1720 bindIntParameter(memberdef_insert,":protectedgettable",md->isProtectedGettable());
1721 bindIntParameter(memberdef_insert,":settable",md->isSettable());
1722 bindIntParameter(memberdef_insert,":privatesettable",md->isPrivateSettable());
1723 bindIntParameter(memberdef_insert,":protectedsettable",md->isProtectedSettable());
1724
1725 if (md->isAssign() || md->isCopy() || md->isRetain()
1726 || md->isStrong() || md->isWeak())
1727 {
1728 int accessor=0;
1729 if (md->isAssign()) accessor = 1;
1730 else if (md->isCopy()) accessor = 2;
1731 else if (md->isRetain()) accessor = 3;
1732 else if (md->isStrong()) accessor = 4;
1733 else if (md->isWeak()) accessor = 5;
1734
1735 bindIntParameter(memberdef_insert,":accessor",accessor);
1736 }
1739 }
1740 else if (md->memberType() == MemberType::Event)
1741 {
1743 bindIntParameter(memberdef_insert,":removable",md->isRemovable());
1744 bindIntParameter(memberdef_insert,":raisable",md->isRaisable());
1745 }
1746
1747 const MemberDef *rmd = md->reimplements();
1748 if (rmd)
1749 {
1750 QCString qreimplemented_refid = rmd->getOutputFileBase() + "_1" + rmd->anchor();
1751
1752 struct Refid reimplemented_refid = insertRefid(qreimplemented_refid);
1753
1754 bindIntParameter(reimplements_insert,":memberdef_rowid", refid.rowid);
1755 bindIntParameter(reimplements_insert,":reimplemented_rowid", reimplemented_refid.rowid);
1757 }
1758
1759 // + declaration/definition arg lists
1760 if (md->memberType()!=MemberType::Define &&
1762 )
1763 {
1765 {
1767 }
1768 QCString typeStr = md->typeString();
1769 stripQualifiers(typeStr);
1770 StringVector list;
1771 linkifyText(TextGeneratorSqlite3Impl(list), def, md->getBodyDef(),md,typeStr);
1772 if (!typeStr.isEmpty())
1773 {
1774 bindTextParameter(memberdef_insert,":type",typeStr);
1775 }
1776
1777 if (!md->definition().isEmpty())
1778 {
1779 bindTextParameter(memberdef_insert,":definition",md->definition());
1780 }
1781
1782 if (!md->argsString().isEmpty())
1783 {
1784 bindTextParameter(memberdef_insert,":argsstring",md->argsString());
1785 }
1786 }
1787
1789
1790 // Extract references from initializer
1792 {
1793 bindTextParameter(memberdef_insert,":initializer",md->initializer());
1794
1795 StringVector list;
1797 for (const auto &s : list)
1798 {
1799 if (md->getBodyDef())
1800 {
1801 DBG_CTX(("initializer:%s %s %s %d\n",
1802 qPrint(md->anchor()),
1803 s.c_str(),
1805 md->getStartBodyLine()));
1806 QCString qsrc_refid = md->getOutputFileBase() + "_1" + md->anchor();
1807 struct Refid src_refid = insertRefid(qsrc_refid);
1808 struct Refid dst_refid = insertRefid(s.c_str());
1809 insertMemberReference(src_refid,dst_refid, "initializer");
1810 }
1811 }
1812 }
1813
1814 if ( !md->getScopeString().isEmpty() )
1815 {
1817 }
1818
1819 // +Brief, detailed and inbody description
1820 getSQLDesc(memberdef_insert,":briefdescription",md->briefDescription(),md);
1821 getSQLDesc(memberdef_insert,":detaileddescription",md->documentation(),md);
1822 getSQLDesc(memberdef_insert,":inbodydescription",md->inbodyDocumentation(),md);
1823
1824 // File location
1825 if (md->getDefLine() != -1)
1826 {
1827 int file_id = insertPath(md->getDefFileName(),!md->isReference());
1828 if (file_id!=-1)
1829 {
1830 bindIntParameter(memberdef_insert,":file_id",file_id);
1833
1834 // definitions also have bodyfile/start/end
1835 if (md->getStartBodyLine()!=-1)
1836 {
1837 int bodyfile_id = insertPath(md->getBodyDef()->absFilePath(),!md->getBodyDef()->isReference());
1838 if (bodyfile_id == -1)
1839 {
1840 sqlite3_clear_bindings(memberdef_insert.stmt);
1841 }
1842 else
1843 {
1844 bindIntParameter(memberdef_insert,":bodyfile_id",bodyfile_id);
1847 }
1848 }
1849 }
1850 }
1851
1852 int memberdef_id=step(memberdef_insert,TRUE);
1853
1854 if (isFunc)
1855 {
1856 insertMemberFunctionParams(memberdef_id,md,def);
1857 }
1858 else if (md->memberType()==MemberType::Define &&
1859 !md->argsString().isEmpty())
1860 {
1861 insertMemberDefineParams(memberdef_id,md,def);
1862 }
1863
1864 // + source references
1865 // The cross-references in initializers only work when both the src and dst
1866 // are defined.
1867 for (const auto &refmd : md->getReferencesMembers())
1868 {
1869 insertMemberReference(md,refmd, "inline");
1870 }
1871 // + source referenced by
1872 for (const auto &refmd : md->getReferencedByMembers())
1873 {
1874 insertMemberReference(refmd,md, "inline");
1875 }
1876}
1877
1879 const MemberList *ml,
1880 struct Refid scope_refid,
1881 const char * /*kind*/,
1882 const QCString & /*header*/=QCString(),
1883 const QCString & /*documentation*/=QCString())
1884{
1885 if (ml==nullptr) return;
1886 for (const auto &md : *ml)
1887 {
1888 // TODO: necessary? just tracking what xmlgen does; xmlgen says:
1889 // namespace members are also inserted in the file scope, but
1890 // to prevent this duplication in the XML output, we filter those here.
1891 if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==nullptr)
1892 {
1893 generateSqlite3ForMember(md, scope_refid, d);
1894 }
1895 }
1896}
1897
1898static void associateAllClassMembers(const ClassDef *cd, struct Refid scope_refid)
1899{
1900 for (auto &mni : cd->memberNameInfoLinkedMap())
1901 {
1902 for (auto &mi : *mni)
1903 {
1904 const MemberDef *md = mi->memberDef();
1905 QCString qrefid = md->getOutputFileBase() + "_1" + md->anchor();
1906 associateMember(md, insertRefid(qrefid), scope_refid);
1907 }
1908 }
1909}
1910
1911// many kinds: category class enum exception interface
1912// module protocol service singleton struct type union
1913// enum is Java only (and is distinct from enum memberdefs)
1914static void generateSqlite3ForClass(const ClassDef *cd)
1915{
1916 // NOTE: Skeptical about XML's version of these
1917 // 'x' marks missing items XML claims to include
1918
1919 // + brief description
1920 // + detailed description
1921 // + template argument list(s)
1922 // + include file
1923 // + member groups
1924 // x inheritance DOT diagram
1925 // + list of direct super classes
1926 // + list of direct sub classes
1927 // + list of inner classes
1928 // x collaboration DOT diagram
1929 // + list of all members
1930 // x user defined member sections
1931 // x standard member sections
1932 // x detailed member documentation
1933 // - examples using the class
1934
1935 if (cd->isReference()) return; // skip external references.
1936 if (cd->isHidden()) return; // skip hidden classes.
1937 if (cd->isAnonymous()) return; // skip anonymous compounds.
1938 if (cd->isImplicitTemplateInstance()) return; // skip generated template instances.
1939
1940 struct Refid refid = insertRefid(cd->getOutputFileBase());
1941
1942 // can omit a class that already has a refid
1943 if(!refid.created && compounddefExists(refid)){return;}
1944
1945 bindIntParameter(compounddef_insert,":rowid", refid.rowid);
1946
1950 bindIntParameter(compounddef_insert,":prot",static_cast<int>(cd->protection()));
1951
1952 int file_id = insertPath(cd->getDefFileName());
1953 bindIntParameter(compounddef_insert,":file_id",file_id);
1956
1957 // + include file
1958 /*
1959 TODO: I wonder if this can actually be cut (just here)
1960
1961 We were adding this "include" to the "includes" table alongside
1962 other includes (from a FileDef). However, FileDef and ClassDef are using
1963 "includes" nodes in very a different way:
1964 - With FileDef, it means the file includes another.
1965 - With ClassDef, it means you should include this file to use this class.
1966
1967 Because of this difference, I added a column to compounddef, header_id, and
1968 linked it back to the appropriate file. We could just add a nullable text
1969 column that would hold a string equivalent to what the HTML docs include,
1970 but the logic for generating it is embedded in
1971 ClassDef::writeIncludeFiles(OutputList &ol).
1972
1973 That said, at least on the handful of test sets I have, header_id == file_id,
1974 suggesting it could be cut and clients might be able to reconstruct it from
1975 other values if there's a solid heuristic for *when a class will
1976 have a header file*.
1977 */
1978 const IncludeInfo *ii=cd->includeInfo();
1979 if (ii)
1980 {
1981 QCString nm = ii->includeName;
1982 if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
1983 if (!nm.isEmpty())
1984 {
1985 int header_id=-1;
1986 if (ii->fileDef)
1987 {
1989 }
1990 DBG_CTX(("-----> ClassDef includeInfo for %s\n", qPrint(nm)));
1991 DBG_CTX((" local : %d\n", ii->local));
1992 DBG_CTX((" imported : %d\n", ii->imported));
1993 if (ii->fileDef)
1994 {
1995 DBG_CTX(("header: %s\n", qPrint(ii->fileDef->absFilePath())));
1996 }
1997 DBG_CTX((" file_id : %d\n", file_id));
1998 DBG_CTX((" header_id: %d\n", header_id));
1999
2000 if(header_id!=-1)
2001 {
2002 bindIntParameter(compounddef_insert,":header_id",header_id);
2003 }
2004 }
2005 }
2006
2007 getSQLDescCompound(compounddef_insert,":briefdescription",cd->briefDescription(),cd);
2008 getSQLDescCompound(compounddef_insert,":detaileddescription",cd->documentation(),cd);
2009
2011
2012 // + list of direct super classes
2013 for (const auto &bcd : cd->baseClasses())
2014 {
2015 struct Refid base_refid = insertRefid(bcd.classDef->getOutputFileBase());
2016 struct Refid derived_refid = insertRefid(cd->getOutputFileBase());
2017 bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid);
2018 bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid);
2019 bindIntParameter(compoundref_insert,":prot",static_cast<int>(bcd.prot));
2020 bindIntParameter(compoundref_insert,":virt",static_cast<int>(bcd.virt));
2022 }
2023
2024 // + list of direct sub classes
2025 for (const auto &bcd : cd->subClasses())
2026 {
2027 struct Refid derived_refid = insertRefid(bcd.classDef->getOutputFileBase());
2028 struct Refid base_refid = insertRefid(cd->getOutputFileBase());
2029 bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid);
2030 bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid);
2031 bindIntParameter(compoundref_insert,":prot",static_cast<int>(bcd.prot));
2032 bindIntParameter(compoundref_insert,":virt",static_cast<int>(bcd.virt));
2034 }
2035
2036 // + list of inner classes
2038
2039 // + template argument list(s)
2041
2042 // + member groups
2043 for (const auto &mg : cd->getMemberGroups())
2044 {
2045 generateSqlite3Section(cd,&mg->members(),refid,"user-defined",mg->header(),
2046 mg->documentation());
2047 }
2048
2049 // this is just a list of *local* members
2050 for (const auto &ml : cd->getMemberLists())
2051 {
2052 if (!ml->listType().isDetailed())
2053 {
2054 generateSqlite3Section(cd,ml.get(),refid,"user-defined");
2055 }
2056 }
2057
2058 // + list of all members
2060}
2061
2063{
2064 if (cd->isReference() || cd->isHidden()) return; // skip external references
2065
2066 struct Refid refid = insertRefid(cd->getOutputFileBase());
2067 if(!refid.created && compounddefExists(refid)){return;}
2068 bindIntParameter(compounddef_insert,":rowid", refid.rowid);
2070 bindTextParameter(compounddef_insert,":kind","concept");
2071
2072 int file_id = insertPath(cd->getDefFileName());
2073 bindIntParameter(compounddef_insert,":file_id",file_id);
2076
2077 getSQLDescCompound(compounddef_insert,":briefdescription",cd->briefDescription(),cd);
2078 getSQLDescCompound(compounddef_insert,":detaileddescription",cd->documentation(),cd);
2079
2081
2082 // + template argument list(s)
2084}
2085
2087{
2088 // + contained class definitions
2089 // + contained concept definitions
2090 // + member groups
2091 // + normal members
2092 // + brief desc
2093 // + detailed desc
2094 // + location (file_id, line, column)
2095 // - exports
2096 // + used files
2097
2098 if (mod->isReference() || mod->isHidden()) return;
2099 struct Refid refid = insertRefid(mod->getOutputFileBase());
2100 if(!refid.created && compounddefExists(refid)){return;}
2101 bindIntParameter(compounddef_insert,":rowid", refid.rowid);
2103 bindTextParameter(compounddef_insert,":kind","module");
2104
2105 int file_id = insertPath(mod->getDefFileName());
2106 bindIntParameter(compounddef_insert,":file_id",file_id);
2109
2110 getSQLDescCompound(compounddef_insert,":briefdescription",mod->briefDescription(),mod);
2111 getSQLDescCompound(compounddef_insert,":detaileddescription",mod->documentation(),mod);
2112
2114
2115 // + contained class definitions
2117
2118 // + contained concept definitions
2120
2121 // + member groups
2122 for (const auto &mg : mod->getMemberGroups())
2123 {
2124 generateSqlite3Section(mod,&mg->members(),refid,"user-defined",mg->header(),
2125 mg->documentation());
2126 }
2127
2128 // + normal members
2129 for (const auto &ml : mod->getMemberLists())
2130 {
2131 if (ml->listType().isDeclaration())
2132 {
2133 generateSqlite3Section(mod,ml.get(),refid,"user-defined");
2134 }
2135 }
2136
2137 // + files
2139}
2140
2141// kinds: constants library module namespace package
2143{
2144 // + contained class definitions
2145 // + contained namespace definitions
2146 // + member groups
2147 // + normal members
2148 // + brief desc
2149 // + detailed desc
2150 // + location (file_id, line, column)
2151 // - files containing (parts of) the namespace definition
2152
2153 if (nd->isReference() || nd->isHidden()) return; // skip external references
2154 struct Refid refid = insertRefid(nd->getOutputFileBase());
2155 if(!refid.created && compounddefExists(refid)){return;}
2156 bindIntParameter(compounddef_insert,":rowid", refid.rowid);
2157
2160 bindTextParameter(compounddef_insert,":kind","namespace");
2161
2162 int file_id = insertPath(nd->getDefFileName());
2163 bindIntParameter(compounddef_insert,":file_id",file_id);
2166
2167 getSQLDescCompound(compounddef_insert,":briefdescription",nd->briefDescription(),nd);
2168 getSQLDescCompound(compounddef_insert,":detaileddescription",nd->documentation(),nd);
2169
2171
2172 // + contained class definitions
2174
2175 // + contained concept definitions
2177
2178 // + contained namespace definitions
2180
2181 // + member groups
2182 for (const auto &mg : nd->getMemberGroups())
2183 {
2184 generateSqlite3Section(nd,&mg->members(),refid,"user-defined",mg->header(),
2185 mg->documentation());
2186 }
2187
2188 // + normal members
2189 for (const auto &ml : nd->getMemberLists())
2190 {
2191 if (ml->listType().isDeclaration())
2192 {
2193 generateSqlite3Section(nd,ml.get(),refid,"user-defined");
2194 }
2195 }
2196}
2197
2198// kind: file
2199static void generateSqlite3ForFile(const FileDef *fd)
2200{
2201 // + includes files
2202 // + includedby files
2203 // x include graph
2204 // x included by graph
2205 // + contained class definitions
2206 // + contained namespace definitions
2207 // + member groups
2208 // + normal members
2209 // + brief desc
2210 // + detailed desc
2211 // x source code
2212 // + location (file_id, line, column)
2213 // - number of lines
2214
2215 if (fd->isReference()) return; // skip external references
2216
2217 struct Refid refid = insertRefid(fd->getOutputFileBase());
2218 if(!refid.created && compounddefExists(refid)){return;}
2219 bindIntParameter(compounddef_insert,":rowid", refid.rowid);
2220
2223 bindTextParameter(compounddef_insert,":kind","file");
2224
2225 int file_id = insertPath(fd->getDefFileName());
2226 bindIntParameter(compounddef_insert,":file_id",file_id);
2229
2230 getSQLDesc(compounddef_insert,":briefdescription",fd->briefDescription(),fd);
2231 getSQLDesc(compounddef_insert,":detaileddescription",fd->documentation(),fd);
2232
2234
2235 // + includes files
2236 for (const auto &ii : fd->includeFileList())
2237 {
2238 int src_id=insertPath(fd->absFilePath(),!fd->isReference());
2239 int dst_id=0;
2240 QCString dst_path;
2241 bool isLocal = (ii.kind & IncludeKind_LocalMask)!=0;
2242
2243 if(ii.fileDef) // found file
2244 {
2245 if(ii.fileDef->isReference())
2246 {
2247 // strip tagfile from path
2248 QCString tagfile = ii.fileDef->getReference();
2249 dst_path = ii.fileDef->absFilePath();
2250 dst_path.stripPrefix(tagfile+":");
2251 }
2252 else
2253 {
2254 dst_path = ii.fileDef->absFilePath();
2255 }
2256 dst_id = insertPath(dst_path,isLocal);
2257 }
2258 else // can't find file
2259 {
2260 dst_id = insertPath(ii.includeName,isLocal,FALSE);
2261 }
2262
2263 DBG_CTX(("-----> FileDef includeInfo for %s\n", qPrint(ii.includeName)));
2264 DBG_CTX((" local: %d\n", isLocal));
2265 DBG_CTX((" imported: %d\n", (ii.kind & IncludeKind_ImportMask)!=0));
2266 if(ii.fileDef)
2267 {
2268 DBG_CTX(("include: %s\n", qPrint(ii.fileDef->absFilePath())));
2269 }
2270 DBG_CTX((" src_id : %d\n", src_id));
2271 DBG_CTX((" dst_id: %d\n", dst_id));
2272
2273 bindIntParameter(incl_select,":local",isLocal);
2274 bindIntParameter(incl_select,":src_id",src_id);
2275 bindIntParameter(incl_select,":dst_id",dst_id);
2276 if (step(incl_select,TRUE,TRUE)==0) {
2277 bindIntParameter(incl_insert,":local",isLocal);
2278 bindIntParameter(incl_insert,":src_id",src_id);
2279 bindIntParameter(incl_insert,":dst_id",dst_id);
2281 }
2282 }
2283
2284 // + includedby files
2285 for (const auto &ii : fd->includedByFileList())
2286 {
2287 int dst_id=insertPath(fd->absFilePath(),!fd->isReference());
2288 int src_id=0;
2289 QCString src_path;
2290 bool isLocal = (ii.kind & IncludeKind_LocalMask)!=0;
2291
2292 if(ii.fileDef) // found file
2293 {
2294 if(ii.fileDef->isReference())
2295 {
2296 // strip tagfile from path
2297 QCString tagfile = ii.fileDef->getReference();
2298 src_path = ii.fileDef->absFilePath();
2299 src_path.stripPrefix(tagfile+":");
2300 }
2301 else
2302 {
2303 src_path = ii.fileDef->absFilePath();
2304 }
2305 src_id = insertPath(src_path,isLocal);
2306 }
2307 else // can't find file
2308 {
2309 src_id = insertPath(ii.includeName,isLocal,FALSE);
2310 }
2311
2312 bindIntParameter(incl_select,":local",isLocal);
2313 bindIntParameter(incl_select,":src_id",src_id);
2314 bindIntParameter(incl_select,":dst_id",dst_id);
2315 if (step(incl_select,TRUE,TRUE)==0) {
2316 bindIntParameter(incl_insert,":local",isLocal);
2317 bindIntParameter(incl_insert,":src_id",src_id);
2318 bindIntParameter(incl_insert,":dst_id",dst_id);
2320 }
2321 }
2322
2323 // + contained class definitions
2325
2326 // + contained concept definitions
2328
2329 // + contained namespace definitions
2331
2332 // + member groups
2333 for (const auto &mg : fd->getMemberGroups())
2334 {
2335 generateSqlite3Section(fd,&mg->members(),refid,"user-defined",mg->header(),
2336 mg->documentation());
2337 }
2338
2339 // + normal members
2340 for (const auto &ml : fd->getMemberLists())
2341 {
2342 if (ml->listType().isDeclaration())
2343 {
2344 generateSqlite3Section(fd,ml.get(),refid,"user-defined");
2345 }
2346 }
2347}
2348
2349// kind: group
2350static void generateSqlite3ForGroup(const GroupDef *gd)
2351{
2352 // + members
2353 // + member groups
2354 // + files
2355 // + classes
2356 // + namespaces
2357 // - packages
2358 // + pages
2359 // + child groups
2360 // - examples
2361 // + brief description
2362 // + detailed description
2363
2364 if (gd->isReference()) return; // skip external references.
2365
2366 struct Refid refid = insertRefid(gd->getOutputFileBase());
2367 if(!refid.created && compounddefExists(refid)){return;}
2368 bindIntParameter(compounddef_insert,":rowid", refid.rowid);
2369
2372 bindTextParameter(compounddef_insert,":kind","group");
2373
2374 int file_id = insertPath(gd->getDefFileName());
2375 bindIntParameter(compounddef_insert,":file_id",file_id);
2378
2379 getSQLDesc(compounddef_insert,":briefdescription",gd->briefDescription(),gd);
2380 getSQLDesc(compounddef_insert,":detaileddescription",gd->documentation(),gd);
2381
2383
2384 // + files
2386
2387 // + classes
2389
2390 // + concepts
2392
2393 // + modules
2395
2396 // + namespaces
2398
2399 // + pages
2401
2402 // + groups
2404
2405 // + member groups
2406 for (const auto &mg : gd->getMemberGroups())
2407 {
2408 generateSqlite3Section(gd,&mg->members(),refid,"user-defined",mg->header(),
2409 mg->documentation());
2410 }
2411
2412 // + members
2413 for (const auto &ml : gd->getMemberLists())
2414 {
2415 if (ml->listType().isDeclaration())
2416 {
2417 generateSqlite3Section(gd,ml.get(),refid,"user-defined");
2418 }
2419 }
2420}
2421
2422// kind: dir
2423static void generateSqlite3ForDir(const DirDef *dd)
2424{
2425 // + dirs
2426 // + files
2427 // + briefdescription
2428 // + detaileddescription
2429 // + location (below uses file_id, line, column; XML just uses file)
2430 if (dd->isReference()) return; // skip external references
2431
2432 struct Refid refid = insertRefid(dd->getOutputFileBase());
2433 if(!refid.created && compounddefExists(refid)){return;}
2434 bindIntParameter(compounddef_insert,":rowid", refid.rowid);
2435
2438
2439 int file_id = insertPath(dd->getDefFileName(),TRUE,TRUE,2);
2440 bindIntParameter(compounddef_insert,":file_id",file_id);
2441
2442 /*
2443 line and column are weird here, but:
2444 - dir goes into compounddef with all of the others
2445 - the semantics would be fine if we set them to NULL here
2446 - but defining line and column as NOT NULL is an important promise
2447 for other compounds, so I don't want to loosen it
2448
2449 For reference, the queries return 1.
2450 0 or -1 make more sense, but I see that as a change for DirDef.
2451 */
2454
2455 getSQLDesc(compounddef_insert,":briefdescription",dd->briefDescription(),dd);
2456 getSQLDesc(compounddef_insert,":detaileddescription",dd->documentation(),dd);
2457
2459
2460 // + files
2462
2463 // + files
2465}
2466
2467// kinds: page, example
2468static void generateSqlite3ForPage(const PageDef *pd,bool isExample)
2469{
2470 // + name
2471 // + title
2472 // + brief description
2473 // + documentation (detailed description)
2474 // + inbody documentation
2475 // + sub pages
2476 if (pd->isReference()) return; // skip external references.
2477
2478 // TODO: do we more special handling if isExample?
2479
2480 QCString qrefid = pd->getOutputFileBase();
2481 if (pd->getGroupDef())
2482 {
2483 qrefid+="_"+pd->name();
2484 }
2485 if (qrefid=="index") qrefid="indexpage"; // to prevent overwriting the generated index page.
2486
2487 struct Refid refid = insertRefid(qrefid);
2488
2489 // can omit a page that already has a refid
2490 if(!refid.created && compounddefExists(refid)){return;}
2491
2493 // + name
2495
2496 QCString title;
2497 if (pd==Doxygen::mainPage.get()) // main page is special
2498 {
2499 if (mainPageHasTitle())
2500 {
2502 }
2503 else
2504 {
2505 title = Config_getString(PROJECT_NAME);
2506 }
2507 }
2508 else
2509 {
2511 if (si)
2512 {
2513 title = si->title();
2514 }
2515 if (title.isEmpty())
2516 {
2517 title = pd->title();
2518 }
2519 }
2520
2521 // + title
2522 bindTextParameter(compounddef_insert,":title",title);
2523
2524 bindTextParameter(compounddef_insert,":kind", isExample ? "example" : "page");
2525
2526 int file_id = insertPath(pd->getDefFileName());
2527
2528 bindIntParameter(compounddef_insert,":file_id",file_id);
2531
2532 // + brief description
2533 getSQLDesc(compounddef_insert,":briefdescription",pd->briefDescription(),pd);
2534 // + documentation (detailed description)
2535 getSQLDesc(compounddef_insert,":detaileddescription",pd->documentation(),pd);
2536
2538 // + sub pages
2540}
2541
2542
2543static sqlite3* openDbConnection()
2544{
2545
2546 QCString outputDirectory = Config_getString(SQLITE3_OUTPUT);
2547 sqlite3 *db = nullptr;
2548
2549 int rc = sqlite3_initialize();
2550 if (rc != SQLITE_OK)
2551 {
2552 err("sqlite3_initialize failed\n");
2553 return nullptr;
2554 }
2555
2556 std::string dbFileName = "doxygen_sqlite3.db";
2557 FileInfo fi(outputDirectory.str()+"/"+dbFileName);
2558
2559 if (fi.exists())
2560 {
2561 if (Config_getBool(SQLITE3_RECREATE_DB))
2562 {
2563 Dir().remove(fi.absFilePath());
2564 }
2565 else
2566 {
2567 err("doxygen_sqlite3.db already exists! Rename, remove, or archive it to regenerate\n");
2568 return nullptr;
2569 }
2570 }
2571
2572 rc = sqlite3_open_v2(
2573 fi.absFilePath().c_str(),
2574 &db,
2575 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
2576 nullptr
2577 );
2578 if (rc != SQLITE_OK)
2579 {
2580 sqlite3_close(db);
2581 err("Database open failed: doxygen_sqlite3.db\n");
2582 }
2583 return db;
2584}
2585//////////////////////////////////////////////////////////////////////////////
2586//////////////////////////////////////////////////////////////////////////////
2588{
2589 // + classes
2590 // + namespaces
2591 // + files
2592 // + groups
2593 // + related pages
2594 // + examples
2595 // + main page
2596 sqlite3 *db = openDbConnection();
2597 if (db==nullptr)
2598 {
2599 return;
2600 }
2601
2602# ifdef SQLITE3_DEBUG
2603 // debug: show all executed statements
2604 sqlite3_trace(db, &sqlLog, nullptr);
2605# endif
2606
2607 beginTransaction(db);
2608 pragmaTuning(db);
2609
2610 if (-1==initializeTables(db))
2611 return;
2612
2613 if ( -1 == prepareStatements(db) )
2614 {
2615 err("sqlite generator: prepareStatements failed!\n");
2616 return;
2617 }
2618
2620
2621 // + classes
2622 for (const auto &cd : *Doxygen::classLinkedMap)
2623 {
2624 msg("Generating Sqlite3 output for class {}\n",cd->name());
2625 generateSqlite3ForClass(cd.get());
2626 }
2627
2628 // + concepts
2629 for (const auto &cd : *Doxygen::conceptLinkedMap)
2630 {
2631 msg("Generating Sqlite3 output for concept {}\n",cd->name());
2632 generateSqlite3ForConcept(cd.get());
2633 }
2634
2635 // + modules
2636 for (const auto &mod : ModuleManager::instance().modules())
2637 {
2638 msg("Generating Sqlite3 output for module {}\n",mod->name());
2639 generateSqlite3ForModule(mod.get());
2640 }
2641
2642 // + namespaces
2643 for (const auto &nd : *Doxygen::namespaceLinkedMap)
2644 {
2645 msg("Generating Sqlite3 output for namespace {}\n",nd->name());
2647 }
2648
2649 // + files
2650 for (const auto &fn : *Doxygen::inputNameLinkedMap)
2651 {
2652 for (const auto &fd : *fn)
2653 {
2654 msg("Generating Sqlite3 output for file {}\n",fd->name());
2655 generateSqlite3ForFile(fd.get());
2656 }
2657 }
2658
2659 // + groups
2660 for (const auto &gd : *Doxygen::groupLinkedMap)
2661 {
2662 msg("Generating Sqlite3 output for group {}\n",gd->name());
2663 generateSqlite3ForGroup(gd.get());
2664 }
2665
2666 // + page
2667 for (const auto &pd : *Doxygen::pageLinkedMap)
2668 {
2669 msg("Generating Sqlite3 output for page {}\n",pd->name());
2670 generateSqlite3ForPage(pd.get(),FALSE);
2671 }
2672
2673 // + dirs
2674 for (const auto &dd : *Doxygen::dirLinkedMap)
2675 {
2676 msg("Generating Sqlite3 output for dir {}\n",dd->name());
2677 generateSqlite3ForDir(dd.get());
2678 }
2679
2680 // + examples
2681 for (const auto &pd : *Doxygen::exampleLinkedMap)
2682 {
2683 msg("Generating Sqlite3 output for example {}\n",pd->name());
2684 generateSqlite3ForPage(pd.get(),TRUE);
2685 }
2686
2687 // + main page
2689 {
2690 msg("Generating Sqlite3 output for the main page\n");
2692 }
2693
2694 // TODO: copied from initializeSchema; not certain if we should say/do more
2695 // if there's a failure here?
2696 if (-1==initializeViews(db))
2697 return;
2698
2699 endTransaction(db);
2700}
2701
2702// vim: noai:ts=2:sw=2:ss=2:expandtab
This class represents an function or template argument list.
Definition arguments.h:65
iterator end()
Definition arguments.h:94
size_t size() const
Definition arguments.h:100
bool constSpecifier() const
Definition arguments.h:111
bool empty() const
Definition arguments.h:99
iterator begin()
Definition arguments.h:93
bool volatileSpecifier() const
Definition arguments.h:112
A abstract class representing of a compound symbol.
Definition classdef.h:104
virtual const ArgumentList & templateArguments() const =0
Returns the template arguments of this class.
virtual QCString compoundTypeString() const =0
Returns the type of compound as a string.
virtual const MemberLists & getMemberLists() const =0
Returns the list containing the list of members sorted per type.
virtual const BaseClassList & baseClasses() const =0
Returns the list of base classes from which this class directly inherits.
virtual Protection protection() const =0
Return the protection level (Public,Protected,Private) in which this compound was found.
virtual const MemberNameInfoLinkedMap & memberNameInfoLinkedMap() const =0
Returns a dictionary of all members.
virtual bool isImplicitTemplateInstance() const =0
virtual const MemberGroupList & getMemberGroups() const =0
Returns the member groups defined for this class.
virtual ClassLinkedRefMap getClasses() const =0
returns the classes nested into this class
virtual FileDef * getFileDef() const =0
Returns the namespace this compound is in, or 0 if it has a global scope.
virtual const IncludeInfo * includeInfo() const =0
virtual QCString title() const =0
virtual const BaseClassList & subClasses() const =0
Returns the list of sub classes that directly derive from this class.
virtual ArgumentList getTemplateParameterList() const =0
virtual const FileDef * getFileDef() const =0
The common base class of all entity definitions found in the sources.
Definition definition.h:76
virtual QCString docFile() const =0
virtual int getEndBodyLine() const =0
virtual int docLine() const =0
virtual QCString getDefFileName() const =0
virtual int getDefLine() const =0
virtual DefType definitionType() const =0
virtual QCString anchor() const =0
virtual const FileDef * getBodyDef() const =0
virtual QCString briefDescription(bool abbreviate=FALSE) const =0
virtual bool isAnonymous() const =0
virtual bool isHidden() const =0
virtual QCString documentation() const =0
virtual QCString displayName(bool includeScope=TRUE) const =0
virtual QCString getOutputFileBase() const =0
virtual Definition * getOuterScope() const =0
virtual const MemberVector & getReferencedByMembers() const =0
virtual int getStartBodyLine() const =0
virtual QCString getDefFileExtension() const =0
virtual int getDefColumn() const =0
virtual bool isReference() const =0
virtual const MemberVector & getReferencesMembers() const =0
virtual QCString inbodyDocumentation() const =0
virtual const QCString & name() const =0
A model of a directory symbol.
Definition dirdef.h:110
virtual const DirList & subDirs() const =0
virtual const FileList & getFiles() const =0
Class representing a directory in the file system.
Definition dir.h:75
bool remove(const std::string &path, bool acceptsAbsPath=true) const
Definition dir.cpp:314
A list of directories.
Definition dirdef.h:178
Class representing the abstract syntax tree of a documentation block.
Definition docnode.h:1466
static NamespaceLinkedMap * namespaceLinkedMap
Definition doxygen.h:115
static ConceptLinkedMap * conceptLinkedMap
Definition doxygen.h:98
static std::unique_ptr< PageDef > mainPage
Definition doxygen.h:101
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:105
static ClassLinkedMap * classLinkedMap
Definition doxygen.h:96
static PageLinkedMap * exampleLinkedMap
Definition doxygen.h:99
static PageLinkedMap * pageLinkedMap
Definition doxygen.h:100
static DirLinkedMap * dirLinkedMap
Definition doxygen.h:129
static GroupLinkedMap * groupLinkedMap
Definition doxygen.h:114
A model of a file symbol.
Definition filedef.h:99
virtual const NamespaceLinkedRefMap & getNamespaces() const =0
virtual const MemberGroupList & getMemberGroups() const =0
virtual QCString absFilePath() const =0
virtual const ClassLinkedRefMap & getClasses() const =0
virtual QCString title() const =0
virtual const IncludeInfoList & includeFileList() const =0
virtual const MemberLists & getMemberLists() const =0
virtual const QCString & docName() const =0
virtual const ConceptLinkedRefMap & getConcepts() const =0
virtual const IncludeInfoList & includedByFileList() const =0
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
bool exists() const
Definition fileinfo.cpp:30
std::string absFilePath() const
Definition fileinfo.cpp:101
A model of a group of symbols.
Definition groupdef.h:52
virtual const GroupList & getSubGroups() const =0
virtual QCString groupTitle() const =0
virtual const FileList & getFiles() const =0
virtual const MemberLists & getMemberLists() const =0
virtual const MemberGroupList & getMemberGroups() const =0
virtual const ConceptLinkedRefMap & getConcepts() const =0
virtual const PageLinkedRefMap & getPages() const =0
virtual const NamespaceLinkedRefMap & getNamespaces() const =0
virtual const ClassLinkedRefMap & getClasses() const =0
virtual const ModuleLinkedRefMap & getModules() const =0
const T * find(const std::string &key) const
Definition linkedmap.h:47
A model of a class/file/namespace member symbol.
Definition memberdef.h:48
virtual QCString typeString() const =0
virtual bool isInitonly() const =0
virtual bool isAssign() const =0
virtual bool isExplicit() const =0
virtual bool isNew() const =0
virtual bool isMaybeVoid() const =0
virtual bool isSealed() const =0
virtual QCString definition() const =0
virtual const ClassDef * getClassDef() const =0
virtual const ArgumentList & templateArguments() const =0
virtual bool isSettable() const =0
virtual bool isRetain() const =0
virtual bool isAddable() const =0
virtual const FileDef * getFileDef() const =0
virtual bool isInline() const =0
virtual const ArgumentList & argumentList() const =0
virtual bool isWritable() const =0
virtual bool isMaybeAmbiguous() const =0
virtual bool isPrivateGettable() const =0
virtual bool isRequired() const =0
virtual bool isAttribute() const =0
virtual bool isExternal() const =0
virtual bool isCopy() const =0
virtual QCString getScopeString() const =0
virtual bool isStatic() const =0
virtual const MemberDef * reimplements() const =0
virtual bool isMaybeDefault() const =0
virtual QCString getWriteAccessor() const =0
virtual bool isPrivateSettable() const =0
virtual QCString bitfieldString() const =0
virtual bool isRaisable() const =0
virtual bool isRemovable() const =0
virtual bool isConstrained() const =0
virtual bool isReadonly() const =0
virtual bool isBound() const =0
virtual bool isProtectedSettable() const =0
virtual bool isProtectedGettable() const =0
virtual bool hasOneLineInitializer() const =0
virtual bool isTransient() const =0
virtual bool hasMultiLineInitializer() const =0
virtual Protection protection() const =0
virtual bool isOptional() const =0
virtual QCString getReadAccessor() const =0
virtual bool isGettable() const =0
virtual MemberType memberType() const =0
virtual bool isReadable() const =0
virtual bool isWeak() const =0
virtual QCString memberTypeName() const =0
virtual bool isStrong() const =0
virtual QCString argsString() const =0
virtual Specifier virtualness(int count=0) const =0
virtual bool isFinal() const =0
virtual const ArgumentList & declArgumentList() const =0
virtual bool isMutable() const =0
virtual bool isProperty() const =0
virtual const QCString & initializer() const =0
A list of MemberDef objects as shown in documentation sections.
Definition memberlist.h:109
MemberListType listType() const
Definition memberlist.h:114
constexpr bool isDetailed() const
Definition types.h:383
constexpr bool isDeclaration() const
Definition types.h:384
virtual const MemberGroupList & getMemberGroups() const =0
virtual const MemberLists & getMemberLists() const =0
virtual FileList getUsedFiles() const =0
virtual const ConceptLinkedRefMap & getConcepts() const =0
virtual const ClassLinkedRefMap & getClasses() const =0
static ModuleManager & instance()
An abstract interface of a namespace symbol.
virtual ConceptLinkedRefMap getConcepts() const =0
virtual const MemberLists & getMemberLists() const =0
virtual NamespaceLinkedRefMap getNamespaces() const =0
virtual QCString title() const =0
virtual ClassLinkedRefMap getClasses() const =0
virtual const MemberGroupList & getMemberGroups() const =0
Class representing a list of different code generators.
Definition outputlist.h:164
void add(OutputCodeIntfPtr &&p)
Definition outputlist.h:194
A model of a page symbol.
Definition pagedef.h:26
virtual const PageLinkedRefMap & getSubPages() const =0
virtual QCString title() const =0
virtual const GroupDef * getGroupDef() const =0
This is an alternative implementation of QCString.
Definition qcstring.h:101
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:226
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:578
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:245
const std::string & str() const
Definition qcstring.h:537
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:159
bool stripPrefix(const QCString &prefix)
Definition qcstring.h:198
class that provide information about a section.
Definition section.h:57
QCString title() const
Definition section.h:69
static SectionManager & instance()
returns a reference to the singleton
Definition section.h:178
Abstract interface for a hyperlinked text fragment.
Definition util.h:64
void writeBreak(int) const override
void writeLink(const QCString &, const QCString &file, const QCString &anchor, std::string_view) const override
TextGeneratorSqlite3Impl(StringVector &l)
void writeString(std::string_view, bool) const override
Text streaming class that buffers data.
Definition textstream.h:36
std::string str() const
Return the contents of the buffer as a std::string object.
Definition textstream.h:229
Concrete visitor implementation for XML output.
#define Config_getBool(name)
Definition config.h:33
#define Config_getString(name)
Definition config.h:32
std::vector< std::string > StringVector
Definition containers.h:33
QCString dateToString(DateTimeType includeTime)
Returns the current date, when includeTime is set also the time is provided.
Definition datetime.cpp:63
IDocNodeASTPtr validatingParseDoc(IDocParser &parserIntf, const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &input, bool indexWords, bool isExample, const QCString &exampleName, bool singleLine, bool linkFromIndex, bool markdownSupport, bool autolinkSupport)
IDocParserPtr createDocParser()
factory function to create a parser
Definition docparser.cpp:55
constexpr uint32_t IncludeKind_ImportMask
Definition filedef.h:65
constexpr uint32_t IncludeKind_LocalMask
Definition filedef.h:63
MemberDef * toMemberDef(Definition *d)
#define msg(fmt,...)
Definition message.h:94
#define err(fmt,...)
Definition message.h:127
const char * qPrint(const char *s)
Definition qcstring.h:672
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34
SqlStmt memberdef_insert
static bool memberdefExists(struct Refid refid)
QCString getSQLDocBlock(const Definition *scope, const Definition *def, const QCString &doc, const QCString &fileName, int lineNr)
static void recordMetadata()
static int prepareStatement(sqlite3 *db, SqlStmt &s)
SqlStmt compounddef_exists
static bool compounddefExists(struct Refid refid)
SqlStmt incl_select
static bool insertMemberReference(struct Refid src_refid, struct Refid dst_refid, const char *context)
#define DBG_CTX(x)
static int initializeTables(sqlite3 *db)
static void generateSqlite3Section(const Definition *d, const MemberList *ml, struct Refid scope_refid, const char *, const QCString &=QCString(), const QCString &=QCString())
static bool memberdefIncomplete(struct Refid refid, const MemberDef *md)
SqlStmt memberdef_incomplete
static void generateSqlite3ForModule(const ModuleDef *mod)
static void getSQLDesc(SqlStmt &s, const char *col, const QCString &value, const Definition *def)
static bool bindTextParameter(SqlStmt &s, const char *name, const QCString &value)
SqlStmt compoundref_insert
static void beginTransaction(sqlite3 *db)
static void generateSqlite3ForConcept(const ConceptDef *cd)
static void insertMemberFunctionParams(int memberdef_id, const MemberDef *md, const Definition *def)
static void writeInnerClasses(const ClassLinkedRefMap &cl, struct Refid outer_refid)
SqlStmt refid_insert
static void generateSqlite3ForGroup(const GroupDef *gd)
static void writeInnerConcepts(const ConceptLinkedRefMap &cl, struct Refid outer_refid)
static void writeInnerGroups(const GroupList &gl, struct Refid outer_refid)
static void writeInnerPages(const PageLinkedRefMap &pl, struct Refid outer_refid)
static void getSQLDescCompound(SqlStmt &s, const char *col, const QCString &value, const Definition *def)
static int insertPath(QCString name, bool local=TRUE, bool found=TRUE, int type=1)
SqlStmt param_select
static void writeInnerNamespaces(const NamespaceLinkedRefMap &nl, struct Refid outer_refid)
static int prepareStatements(sqlite3 *db)
SqlStmt xrefs_insert
static void writeInnerModules(const ModuleLinkedRefMap &ml, struct Refid outer_refid)
SqlStmt reimplements_insert
static void insertMemberDefineParams(int memberdef_id, const MemberDef *md, const Definition *def)
static void writeTemplateList(const ClassDef *cd)
const char * table_schema[][2]
static void endTransaction(sqlite3 *db)
SqlStmt member_insert
static void stripQualifiers(QCString &typeStr)
static void writeTemplateArgumentList(const ArgumentList &al, const Definition *scope, const FileDef *fileScope)
static void associateAllClassMembers(const ClassDef *cd, struct Refid scope_refid)
struct Refid insertRefid(const QCString &refid)
static void generateSqlite3ForDir(const DirDef *dd)
SqlStmt memberdef_update_def
SqlStmt contains_insert
const char * view_schema[][2]
SqlStmt incl_insert
SqlStmt memberdef_update_decl
static void writeInnerFiles(const FileList &fl, struct Refid outer_refid)
SqlStmt memberdef_param_insert
static int initializeViews(sqlite3 *db)
static int step(SqlStmt &s, bool getRowId=FALSE, bool select=FALSE)
SqlStmt path_insert
static sqlite3 * openDbConnection()
SqlStmt meta_insert
static void generateSqlite3ForClass(const ClassDef *cd)
static void writeInnerDirs(const DirList &dl, struct Refid outer_refid)
static void generateSqlite3ForNamespace(const NamespaceDef *nd)
SqlStmt memberdef_exists
static void writeMemberTemplateLists(const MemberDef *md)
static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_refid, const Definition *def)
void generateSqlite3()
static void generateSqlite3ForFile(const FileDef *fd)
SqlStmt path_select
static void generateSqlite3ForPage(const PageDef *pd, bool isExample)
SqlStmt param_insert
SqlStmt refid_select
static void pragmaTuning(sqlite3 *db)
SqlStmt compounddef_insert
static bool bindIntParameter(SqlStmt &s, const char *name, int value)
static void associateMember(const MemberDef *md, struct Refid member_refid, struct Refid scope_refid)
This class contains the information about the argument of a function or template.
Definition arguments.h:27
QCString name
Definition arguments.h:44
Class representing the data associated with a #include statement.
Definition filedef.h:75
QCString includeName
Definition filedef.h:80
const FileDef * fileDef
Definition filedef.h:79
bool created
QCString refid
int rowid
const char * query
sqlite3 * db
sqlite3_stmt * stmt
@ Enumeration
Definition types.h:557
@ EnumValue
Definition types.h:558
@ Variable
Definition types.h:555
@ Property
Definition types.h:563
@ Typedef
Definition types.h:556
@ Function
Definition types.h:554
bool mainPageHasTitle()
Definition util.cpp:6795
QCString filterTitle(const QCString &title)
Definition util.cpp:6127
static QCString stripFromPath(const QCString &p, const StringVector &l)
Definition util.cpp:310
void linkifyText(const TextGeneratorIntf &out, const Definition *scope, const FileDef *fileScope, const Definition *self, const QCString &text, bool autoBreak, bool external, bool keepSpaces, int indentLevel)
Definition util.cpp:905
QCString convertCharEntitiesToUTF8(const QCString &str)
Definition util.cpp:4557
A bunch of utility functions.