1
/*
2
 * This file is part of the API Extractor project.
3
 *
4
 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
5
 *
6
 * Contact: PySide team <contact@pyside.org>
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * version 2 as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20
 * 02110-1301 USA
21
 *
22
 */
23
24
#include "doxygenparser.h"
25
#include "abstractmetalang.h"
26
#include "reporthandler.h"
27
28
#include <QtXmlPatterns/QXmlQuery>
29
30
namespace
31
{
32
33
QString getSectionKindAttr(const AbstractMetaFunction* func)
34
{
35
    if (func->isSignal()) {
36
        return QLatin1String("signal");
37
    } else {
38
        QString kind = func->isPublic() ? QLatin1String("public") : QLatin1String("protected");
39
        if (func->isStatic())
40
            kind += QLatin1String("-static");
41
        else if (func->isSlot())
42
            kind += QLatin1String("-slot");
43
        return kind;
44
    }
45
}
46
47
}
48
49
Documentation DoxygenParser::retrieveModuleDocumentation()
50
{
51
        return retrieveModuleDocumentation(packageName());
52
}
53
54
void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass)
55
{
56
    if (!metaClass)
57
        return;
58
59
    QString doxyFileSuffix;
60
    if (metaClass->enclosingClass()) {
61
        doxyFileSuffix += metaClass->enclosingClass()->name();
62
        doxyFileSuffix += "_1_1"; // FIXME: Check why _1_1!!
63
    }
64
    doxyFileSuffix += metaClass->name();
65
    doxyFileSuffix += ".xml";
66
67
    const char* prefixes[] = { "class", "struct", "namespace" };
68
    const int numPrefixes = sizeof(prefixes) / sizeof(const char*);
69
    bool isProperty = false;
70
71
    QString doxyFilePath;
72
    for (int i = 0; i < numPrefixes; ++i) {
73
        doxyFilePath = documentationDataDirectory() + "/" + prefixes[i] + doxyFileSuffix;
74
        if (QFile::exists(doxyFilePath))
75
            break;
76
        doxyFilePath.clear();
77
    }
78
79
    if (doxyFilePath.isEmpty()) {
80
        ReportHandler::warning("Can't find doxygen file for class "
81
                               + metaClass->name() + ", tried: "
82
                               + documentationDataDirectory() + "/{struct|class|namespace}"
83
                               + doxyFileSuffix);
84
        return;
85
    }
86
    QXmlQuery xquery;
87
    xquery.setFocus(QUrl(doxyFilePath));
88
89
    // Get class documentation
90
    QString classDoc = getDocumentation(xquery, "/doxygen/compounddef/detaileddescription",
91
                                        metaClass->typeEntry()->docModifications());
92
    if (classDoc.isEmpty()) {
93
        ReportHandler::warning("Can't find documentation for class \""
94
                               + metaClass->name() + "\".");
95
    }
96
    metaClass->setDocumentation(classDoc);
97
98
    //Functions Documentation
99
    AbstractMetaFunctionList funcs = metaClass->functionsInTargetLang();
100
    foreach (AbstractMetaFunction *func, funcs) {
101
        if (!func || func->isPrivate())
102
            continue;
103
104
        QString query = "/doxygen/compounddef/sectiondef";
105
        // properties
106
        if (func->isPropertyReader() || func->isPropertyWriter()
107
            || func->isPropertyResetter()) {
108
            query += "[@kind=\"property\"]/memberdef/name[text()=\""
109
                     + func->propertySpec()->name() + "\"]";
110
            isProperty = true;
111
        } else { // normal methods
112
            QString kind = getSectionKindAttr(func);
113
            query += "[@kind=\"" + kind + "-func\"]/memberdef/name[text()=\""
114
                     + func->originalName() + "\"]";
115
116
            if (func->arguments().isEmpty()) {
117
                QString args = func->isConstant() ? "() const " : "()";
118
                query += "/../argsstring[text()=\"" + args + "\"]";
119
            } else {
120
                int i = 1;
121
                foreach (AbstractMetaArgument* arg, func->arguments()) {
122
                    QString type;
123
                    if (!arg->type()->isPrimitive()) {
124
                        query += "/../param[" + QString::number(i) + "]/type/ref[text()=\""
125
                                 + arg->type()->name() + "\"]/../..";
126
                    } else {
127
                        query += "/../param[" + QString::number(i) + "]/type[text()=\""
128
                                 + arg->type()->name() + "\"]/..";
129
                    }
130
                    ++i;
131
                }
132
            }
133
        }
134
        if (!isProperty) {
135
            query += "/../detaileddescription";
136
        } else {
137
            query = "(" + query;
138
            query += "/../detaileddescription)[1]";
139
        }
140
        QString doc = getDocumentation(xquery, query, DocModificationList());
141
        func->setDocumentation(doc);
142
        isProperty = false;
143
    }
144
145
    //Fields
146
    AbstractMetaFieldList fields = metaClass->fields();
147
    foreach (AbstractMetaField *field, fields) {
148
        if (field->isPrivate())
149
            return;
150
151
        QString query = "/doxygen/compounddef/sectiondef/memberdef/name[text()=\""
152
                        + field->name() + "\"]/../detaileddescription";
153
        QString doc = getDocumentation(xquery, query, DocModificationList());
154
        field->setDocumentation(doc);
155
    }
156
157
    //Enums
158
    AbstractMetaEnumList enums = metaClass->enums();
159
    foreach (AbstractMetaEnum *meta_enum, enums) {
160
        QString query = "/doxygen/compounddef/sectiondef/memberdef[@kind=\"enum\"]/name[text()=\"" + meta_enum->name() + "\"]/..";
161
        QString doc = getDocumentation(xquery, query, DocModificationList());
162
        meta_enum->setDocumentation(doc);
163
    }
164
165
}
166
167
Documentation DoxygenParser::retrieveModuleDocumentation(const QString& name){
168
169
    QString sourceFile = documentationDataDirectory() + '/' + "indexpage.xml";
170
171
    if (!QFile::exists(sourceFile)) {
172
        ReportHandler::warning("Can't find doxygen XML file for module "
173
                               + name + ", tried: "
174
                                                 + sourceFile);
175
        return Documentation();
176
    }
177
178
    QXmlQuery xquery;
179
    xquery.setFocus(QUrl(sourceFile));
180
181
    // Module documentation
182
    QString query = "/doxygen/compounddef/detaileddescription";
183
    return Documentation(getDocumentation(xquery, query, DocModificationList()));
184
}