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