searchsymbols.cpp 9.17 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3 4
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8 9 10 11
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
12 13 14
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
15
**
16 17 18 19 20 21 22
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
con's avatar
con committed
23
**
hjk's avatar
hjk committed
24
****************************************************************************/
25 26 27

#include "searchsymbols.h"

28
#include <cplusplus/LookupContext.h>
29 30
#include <utils/qtcassert.h>
#include <utils/scopedswap.h>
31

Roberto Raggi's avatar
Roberto Raggi committed
32
#include <QDebug>
33 34

using namespace CPlusPlus;
35 36

namespace CppTools {
37

38
typedef Utils::ScopedSwap<IndexItem::Ptr> ScopedIndexItemPtr;
39 40
typedef Utils::ScopedSwap<QString> ScopedScope;

41
SearchSymbols::SymbolTypes SearchSymbols::AllTypes =
42 43 44 45
        SymbolSearcher::Classes
        | SymbolSearcher::Functions
        | SymbolSearcher::Enums
        | SymbolSearcher::Declarations;
46

47
SearchSymbols::SearchSymbols(Internal::StringTable &stringTable)
48 49
    : strings(stringTable)
    , symbolsToSearchFor(SymbolSearcher::Classes | SymbolSearcher::Functions | SymbolSearcher::Enums)
50 51 52
{
}

53
void SearchSymbols::setSymbolsToSearchFor(const SymbolTypes &types)
54
{
55
    symbolsToSearchFor = types;
56 57
}

58
IndexItem::Ptr SearchSymbols::operator()(Document::Ptr doc, const QString &scope)
59
{
60
    IndexItem::Ptr root = IndexItem::create(findOrInsert(doc->fileName()), 100);
61 62

    { // RAII scope
63
        ScopedIndexItemPtr parentRaii(_parent, root);
64 65 66
        QString newScope = scope;
        ScopedScope scopeRaii(_scope, newScope);

67 68
        QTC_ASSERT(_parent, return IndexItem::Ptr());
        QTC_ASSERT(root, return IndexItem::Ptr());
69
        QTC_ASSERT(_parent->fileName() == findOrInsert(doc->fileName()),
70
                   return IndexItem::Ptr());
71 72 73 74 75 76

        for (unsigned i = 0, ei = doc->globalSymbolCount(); i != ei; ++i)
            accept(doc->globalSymbolAt(i));

        strings.scheduleGC();
        m_paths.clear();
77 78
    }

79 80
    root->squeeze();
    return root;
81 82 83 84
}

bool SearchSymbols::visit(Enum *symbol)
{
85
    if (!(symbolsToSearchFor & SymbolSearcher::Enums))
86 87
        return false;

88
    QString name = overview.prettyName(symbol->name());
89
    IndexItem::Ptr newParent = addChildItem(name, QString(), _scope, IndexItem::Enum, symbol);
90 91
    if (!newParent)
        newParent = _parent;
92
    ScopedIndexItemPtr parentRaii(_parent, newParent);
93 94 95 96 97

    QString newScope = scopedSymbolName(name, symbol);
    ScopedScope scopeRaii(_scope, newScope);

    for (unsigned i = 0, ei = symbol->memberCount(); i != ei; ++i)
98
        accept(symbol->memberAt(i));
99

100 101 102 103 104
    return false;
}

bool SearchSymbols::visit(Function *symbol)
{
105
    processFunction(symbol);
106 107 108 109 110
    return false;
}

bool SearchSymbols::visit(Namespace *symbol)
{
Roberto Raggi's avatar
Roberto Raggi committed
111
    QString name = scopedSymbolName(symbol);
112 113
    QString newScope = name;
    ScopedScope raii(_scope, newScope);
114 115
    for (unsigned i = 0; i < symbol->memberCount(); ++i) {
        accept(symbol->memberAt(i));
116 117 118 119 120 121
    }
    return false;
}

bool SearchSymbols::visit(Declaration *symbol)
{
122
    if (!(symbolsToSearchFor & SymbolSearcher::Declarations)) {
123
        // if we're searching for functions, still allow signal declarations to show up.
124
        if (symbolsToSearchFor & SymbolSearcher::Functions) {
125
            Function *funTy = symbol->type()->asFunctionType();
126 127 128 129
            if (!funTy) {
                if (!symbol->type()->asObjCMethodType())
                    return false;
            } else if (!funTy->isSignal()) {
130
                return false;
131
            }
132 133 134 135
        } else {
            return false;
        }
    }
136

137 138 139
    if (symbol->name()) {
        QString name = overview.prettyName(symbol->name());
        QString type = overview.prettyType(symbol->type());
140
        addChildItem(name, type, _scope,
141 142
                     symbol->type()->asFunctionType() ? IndexItem::Function
                                                      : IndexItem::Declaration,
143
                     symbol);
144 145
    }

146 147 148 149 150
    return false;
}

bool SearchSymbols::visit(Class *symbol)
{
151
    processClass(symbol);
152

153 154 155
    return false;
}

156
bool SearchSymbols::visit(UsingNamespaceDirective *)
Roberto Raggi's avatar
Roberto Raggi committed
157 158 159 160
{
    return false;
}

161
bool SearchSymbols::visit(UsingDeclaration *)
Roberto Raggi's avatar
Roberto Raggi committed
162 163 164 165
{
    return false;
}

166
bool SearchSymbols::visit(NamespaceAlias *)
Roberto Raggi's avatar
Roberto Raggi committed
167 168 169 170
{
    return false;
}

171
bool SearchSymbols::visit(Argument *)
Roberto Raggi's avatar
Roberto Raggi committed
172 173 174 175
{
    return false;
}

176
bool SearchSymbols::visit(TypenameArgument *)
Roberto Raggi's avatar
Roberto Raggi committed
177 178 179 180
{
    return false;
}

181
bool SearchSymbols::visit(BaseClass *)
Roberto Raggi's avatar
Roberto Raggi committed
182 183 184 185
{
    return false;
}

186
bool SearchSymbols::visit(Template *)
Roberto Raggi's avatar
Roberto Raggi committed
187 188 189 190
{
    return true;
}

191
bool SearchSymbols::visit(Block *)
Roberto Raggi's avatar
Roberto Raggi committed
192 193 194 195
{
    return false;
}

196
bool SearchSymbols::visit(ForwardClassDeclaration *)
Roberto Raggi's avatar
Roberto Raggi committed
197 198 199 200
{
    return false;
}

201
bool SearchSymbols::visit(ObjCBaseClass *)
Roberto Raggi's avatar
Roberto Raggi committed
202 203 204 205
{
    return false;
}

206
bool SearchSymbols::visit(ObjCBaseProtocol *)
Roberto Raggi's avatar
Roberto Raggi committed
207 208 209 210
{
    return false;
}

211
bool SearchSymbols::visit(ObjCClass *symbol)
Roberto Raggi's avatar
Roberto Raggi committed
212
{
213 214
    processClass(symbol);

Roberto Raggi's avatar
Roberto Raggi committed
215 216 217
    return false;
}

218
bool SearchSymbols::visit(ObjCForwardClassDeclaration *)
Roberto Raggi's avatar
Roberto Raggi committed
219 220 221 222
{
    return false;
}

223
bool SearchSymbols::visit(ObjCProtocol *symbol)
Roberto Raggi's avatar
Roberto Raggi committed
224
{
225 226
    processClass(symbol);

Roberto Raggi's avatar
Roberto Raggi committed
227 228 229
    return false;
}

230
bool SearchSymbols::visit(ObjCForwardProtocolDeclaration *)
Roberto Raggi's avatar
Roberto Raggi committed
231 232 233 234
{
    return false;
}

235
bool SearchSymbols::visit(ObjCMethod *symbol)
Roberto Raggi's avatar
Roberto Raggi committed
236
{
237
    processFunction(symbol);
Roberto Raggi's avatar
Roberto Raggi committed
238 239 240
    return false;
}

241
bool SearchSymbols::visit(ObjCPropertyDeclaration *symbol)
Roberto Raggi's avatar
Roberto Raggi committed
242
{
243
    processFunction(symbol);
Roberto Raggi's avatar
Roberto Raggi committed
244 245 246
    return false;
}

247
QString SearchSymbols::scopedSymbolName(const QString &symbolName, const Symbol *symbol) const
248 249
{
    QString name = _scope;
250
    if (!name.isEmpty())
251
        name += QLatin1String("::");
252
    name += scopeName(symbolName, symbol);
253 254 255 256 257
    return name;
}

QString SearchSymbols::scopedSymbolName(const Symbol *symbol) const
{
258
    return scopedSymbolName(overview.prettyName(symbol->name()), symbol);
259 260
}

261
QString SearchSymbols::scopeName(const QString &name, const Symbol *symbol) const
262
{
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
    if (!name.isEmpty())
        return name;

    if (symbol->isNamespace()) {
        return QLatin1String("<anonymous namespace>");
    } else if (symbol->isEnum()) {
        return QLatin1String("<anonymous enum>");
    } else if (const Class *c = symbol->asClass())  {
        if (c->isUnion())
            return QLatin1String("<anonymous union>");
        else if (c->isStruct())
            return QLatin1String("<anonymous struct>");
        else
            return QLatin1String("<anonymous class>");
    } else {
        return QLatin1String("<anonymous symbol>");
279
    }
280 281
}

282 283 284
IndexItem::Ptr SearchSymbols::addChildItem(const QString &symbolName, const QString &symbolType,
                                           const QString &symbolScope, IndexItem::ItemType itemType,
                                           Symbol *symbol)
285
{
286
    if (!symbol->name() || symbol->isGenerated())
287
        return IndexItem::Ptr();
288

289 290 291 292 293 294
    QString path = m_paths.value(symbol->fileId(), QString());
    if (path.isEmpty()) {
        path = QString::fromUtf8(symbol->fileName(), symbol->fileNameLength());
        m_paths.insert(symbol->fileId(), path);
    }

295
    const QIcon icon = icons.iconForSymbol(symbol);
296 297 298 299 300 301 302 303
    IndexItem::Ptr newItem = IndexItem::create(findOrInsert(symbolName),
                                               findOrInsert(symbolType),
                                               findOrInsert(symbolScope),
                                               itemType,
                                               findOrInsert(path),
                                               symbol->line(),
                                               symbol->column() - 1, // 1-based vs 0-based column
                                               icon);
304 305 306
    _parent->addChild(newItem);
    return newItem;
}
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334

template<class T>
void SearchSymbols::processClass(T *clazz)
{
    QString name = overview.prettyName(clazz->name());

    IndexItem::Ptr newParent;
    if (symbolsToSearchFor & SymbolSearcher::Classes)
        newParent = addChildItem(name, QString(), _scope, IndexItem::Class, clazz);
    if (!newParent)
        newParent = _parent;
    ScopedIndexItemPtr parentRaii(_parent, newParent);

    QString newScope = scopedSymbolName(name, clazz);
    ScopedScope scopeRaii(_scope, newScope);
    for (unsigned i = 0, ei = clazz->memberCount(); i != ei; ++i)
        accept(clazz->memberAt(i));
}

template<class T>
void SearchSymbols::processFunction(T *func)
{
    if (!(symbolsToSearchFor & SymbolSearcher::Functions) || !func->name())
        return;
    QString name = overview.prettyName(func->name());
    QString type = overview.prettyType(func->type());
    addChildItem(name, type, _scope, IndexItem::Function, func);
}
335 336

} // namespace CppTools