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 "qtdocparser.h"
25
#include "reporthandler.h"
26
#include <QtXmlPatterns/QXmlQuery>
27
#include <QUrl>
28
29
Documentation QtDocParser::retrieveModuleDocumentation()
30
{
31
    return retrieveModuleDocumentation(packageName());
32
}
33
34
void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass)
35
{
36
    if (!metaClass)
37
        return;
38
39
    QString scope = metaClass->name();
40
    const AbstractMetaClass* context = metaClass->enclosingClass();
41
    while(context) {
42
        if (context->enclosingClass() == 0)
43
            break;
44
        context = context->enclosingClass();
45
    }
46
47
    QString filename = metaClass->qualifiedCppName().toLower().replace("::", "-");
48
    QString sourceFile = documentationDataDirectory() + '/' + filename + ".xml";
49
    if (metaClass->enclosingClass())
50
        sourceFile.replace("::", "-");
51
52
    if (!QFile::exists(sourceFile)) {
53
        ReportHandler::warning("Can't find qdoc3 file for class "
54
                               + metaClass->name() + ", tried: "
55
                               + sourceFile);
56
        return;
57
    }
58
59
    QXmlQuery xquery;
60
    xquery.setFocus(QUrl(sourceFile));
61
62
    QString className = metaClass->name();
63
64
    // Class/Namespace documentation
65
    QString type = metaClass->isNamespace() ? QLatin1String("namespace") : QLatin1String("class");
66
    QString query = "/WebXML/document/" + type + "[@name=\"" + className + "\"]/description";
67
68
    DocModificationList signedModifs, classModifs;
69
    foreach (DocModification docModif, metaClass->typeEntry()->docModifications()) {
70
        if (docModif.signature().isEmpty())
71
            classModifs.append(docModif);
72
        else
73
            signedModifs.append(docModif);
74
    }
75
76
    Documentation doc(getDocumentation(xquery, query, classModifs));
77
    metaClass->setDocumentation(doc);
78
79
80
    //Functions Documentation
81
    AbstractMetaFunctionList funcs = metaClass->functionsInTargetLang();
82
    foreach (AbstractMetaFunction *func, funcs) {
83
        if (!func || func->isPrivate())
84
            continue;
85
86
        QString query = "/WebXML/document/" + type + "[@" + "name" + "=\"" + className + "\"]";
87
        // properties
88
        if (func->isPropertyReader() || func->isPropertyWriter() || func->isPropertyResetter()) {
89
            query += "/property[@name=\"" + func->propertySpec()->name() + "\"]";
90
        } else { // normal methods
91
            QString isConst = func->isConstant() ? "true" : "false";
92
            query += "/function[@name=\"" + func->originalName()
93
                     + "\" and count(parameter)="
94
                     + QString::number(func->arguments().count())
95
                     + " and @const=\"" + isConst + "\"]";
96
97
            int i = 1;
98
            foreach (AbstractMetaArgument* arg, func->arguments()) {
99
                QString type = arg->type()->name();
100
101
                if (arg->type()->isConstant())
102
                    type.prepend("const ");
103
104
                if (arg->type()->isReference()) {
105
                    type += " &";
106
                } if (arg->type()->indirections()) {
107
                    type += ' ';
108
                    for (int j = 0, max = arg->type()->indirections(); j < max; ++j)
109
                        type += '*';
110
                }
111
                query += "/parameter[" + QString::number(i) + "][@left=\"" + type + "\"]/..";
112
                ++i;
113
            }
114
        }
115
        query += "/description";
116
        DocModificationList funcModifs;
117
        foreach (DocModification funcModif, signedModifs) {
118
            if (funcModif.signature() == func->minimalSignature())
119
                funcModifs.append(funcModif);
120
        }
121
        doc.setValue(getDocumentation(xquery, query, funcModifs));
122
        func->setDocumentation(doc);
123
    }
124
#if 0
125
    // Fields
126
    AbstractMetaFieldList fields = metaClass->fields();
127
    foreach (AbstractMetaField *field, fields) {
128
        if (field->isPrivate())
129
            return;
130
131
        QString query = "/doxygen/compounddef/sectiondef/memberdef/name[text()=\"" + field->name() + "\"]/..";
132
        Documentation doc = getDocumentation(DocModificationList(), xquery, query);
133
        field->setDocumentation(doc);
134
    }
135
#endif
136
    // Enums
137
    AbstractMetaEnumList enums = metaClass->enums();
138
    foreach (AbstractMetaEnum *meta_enum, enums) {
139
        QString query = "/WebXML/document/" + type + "[@" + "name" + "=\""
140
                        + className + "\"]/enum[@name=\""
141
                        + meta_enum->name() + "\"]/description";
142
        doc.setValue(getDocumentation(xquery, query, DocModificationList()));
143
        meta_enum->setDocumentation(doc);
144
    }
145
}
146
147
Documentation QtDocParser::retrieveModuleDocumentation(const QString& name)
148
{
149
    // TODO: This method of acquiring the module name supposes that the target language uses
150
    // dots as module separators in package names. Improve this.
151
    QString moduleName = QString(name).remove(0, name.lastIndexOf('.') + 1);
152
    QString sourceFile = documentationDataDirectory() + '/' + moduleName.toLower() + ".xml";
153
154
    if (!QFile::exists(sourceFile)) {
155
        ReportHandler::warning("Can't find qdoc3 file for module "
156
                               + name + ", tried: "
157
                                                 + sourceFile);
158
        return Documentation();
159
    }
160
161
    QXmlQuery xquery;
162
    xquery.setFocus(QUrl(sourceFile));
163
164
    // Module documentation
165
    QString query = "/WebXML/document/page[@name=\"" + moduleName + "\"]/description";
166
    return Documentation(getDocumentation(xquery, query, DocModificationList()));
167
}