searchsymbols.cpp 8.76 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8 9 10 11 12 13 14
** 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
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17 18 19 20 21 22 23 24 25
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26 27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
29 30 31

#include "searchsymbols.h"

32
#include <cplusplus/LookupContext.h>
33

Roberto Raggi's avatar
Roberto Raggi committed
34
#include <QDebug>
35 36

using namespace CPlusPlus;
37
using namespace CppTools;
38

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

45 46
SearchSymbols::SearchSymbols() :
    symbolsToSearchFor(SymbolSearcher::Classes | SymbolSearcher::Functions | SymbolSearcher::Enums)
47 48 49
{
}

50
void SearchSymbols::setSymbolsToSearchFor(SymbolTypes types)
51
{
52
    symbolsToSearchFor = types;
53 54
}

55
QList<ModelItemInfo> SearchSymbols::operator()(Document::Ptr doc, int sizeHint, const QString &scope)
56 57 58
{
    QString previousScope = switchScope(scope);
    items.clear();
59
    items.reserve(sizeHint);
60 61 62 63
    for (unsigned i = 0; i < doc->globalSymbolCount(); ++i) {
        accept(doc->globalSymbolAt(i));
    }
    (void) switchScope(previousScope);
Roberto Raggi's avatar
Roberto Raggi committed
64
    QList<ModelItemInfo> result = items;
65
    strings.clear();
Roberto Raggi's avatar
Roberto Raggi committed
66 67 68
    items.clear();
    m_paths.clear();
    return result;
69 70 71 72 73 74 75 76 77 78 79
}

QString SearchSymbols::switchScope(const QString &scope)
{
    QString previousScope = _scope;
    _scope = scope;
    return previousScope;
}

bool SearchSymbols::visit(Enum *symbol)
{
80
    if (!(symbolsToSearchFor & SymbolSearcher::Enums))
81 82 83
        return false;

    QString name = symbolName(symbol);
84 85
    QString scopedName = scopedSymbolName(name);
    QString previousScope = switchScope(scopedName);
86
    appendItem(name, QString(), previousScope, ModelItemInfo::Enum, symbol);
87 88
    for (unsigned i = 0; i < symbol->memberCount(); ++i) {
        accept(symbol->memberAt(i));
89 90 91 92 93 94 95
    }
    (void) switchScope(previousScope);
    return false;
}

bool SearchSymbols::visit(Function *symbol)
{
96
    if (!(symbolsToSearchFor & SymbolSearcher::Functions))
97 98
        return false;

99
    QString extraScope;
Roberto Raggi's avatar
Roberto Raggi committed
100
    if (const Name *name = symbol->name()) {
101 102 103
        if (const QualifiedNameId *q = name->asQualifiedNameId()) {
            if (q->base())
                extraScope = overview.prettyName(q->base());
104 105 106 107 108 109
        }
    }
    QString fullScope = _scope;
    if (!_scope.isEmpty() && !extraScope.isEmpty())
        fullScope += QLatin1String("::");
    fullScope += extraScope;
110
    QString name = symbolName(symbol);
111 112
    QString type = overview.prettyType(symbol->type());
    appendItem(name, type, fullScope, ModelItemInfo::Method, symbol);
113 114 115 116 117
    return false;
}

bool SearchSymbols::visit(Namespace *symbol)
{
Roberto Raggi's avatar
Roberto Raggi committed
118
    QString name = scopedSymbolName(symbol);
119
    QString previousScope = switchScope(name);
120 121
    for (unsigned i = 0; i < symbol->memberCount(); ++i) {
        accept(symbol->memberAt(i));
122 123 124 125 126 127 128
    }
    (void) switchScope(previousScope);
    return false;
}

bool SearchSymbols::visit(Declaration *symbol)
{
129
    if (!(symbolsToSearchFor & SymbolSearcher::Declarations)) {
130
        // if we're searching for functions, still allow signal declarations to show up.
131
        if (symbolsToSearchFor & SymbolSearcher::Functions) {
132 133 134 135
            Function *funTy = symbol->type()->asFunctionType();
            if (!funTy)
                return false;
            if (!funTy->isSignal())
136 137 138 139 140
                return false;
        } else {
            return false;
        }
    }
141 142

    QString name = symbolName(symbol);
143 144
    QString type = overview.prettyType(symbol->type());
    appendItem(name, type, _scope,
145 146 147
               symbol->type()->asFunctionType() ? ModelItemInfo::Method
                                                : ModelItemInfo::Declaration,
               symbol);
148 149 150 151 152 153
    return false;
}

bool SearchSymbols::visit(Class *symbol)
{
    QString name = symbolName(symbol);
154 155
    QString scopedName = scopedSymbolName(name);
    QString previousScope = switchScope(scopedName);
156
    if (symbolsToSearchFor & SymbolSearcher::Classes) {
157
        appendItem(name, QString(), previousScope, ModelItemInfo::Class, symbol);
158
    }
159 160
    for (unsigned i = 0; i < symbol->memberCount(); ++i) {
        accept(symbol->memberAt(i));
161 162 163 164 165
    }
    (void) switchScope(previousScope);
    return false;
}

Roberto Raggi's avatar
Roberto Raggi committed
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
bool SearchSymbols::visit(CPlusPlus::UsingNamespaceDirective *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::UsingDeclaration *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::NamespaceAlias *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::Argument *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::TypenameArgument *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::BaseClass *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::Template *)
{
    return true;
}

bool SearchSymbols::visit(CPlusPlus::Block *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::ForwardClassDeclaration *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::ObjCBaseClass *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::ObjCBaseProtocol *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::ObjCClass *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::ObjCForwardClassDeclaration *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::ObjCProtocol *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::ObjCForwardProtocolDeclaration *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::ObjCMethod *)
{
    return false;
}

bool SearchSymbols::visit(CPlusPlus::ObjCPropertyDeclaration *)
{
    return false;
}

251
QString SearchSymbols::scopedSymbolName(const QString &symbolName) const
252 253
{
    QString name = _scope;
254
    if (!name.isEmpty())
255
        name += QLatin1String("::");
256 257 258 259 260 261 262 263 264 265 266
    name += symbolName;
    return name;
}

QString SearchSymbols::scopedSymbolName(const Symbol *symbol) const
{
    return scopedSymbolName(symbolName(symbol));
}

QString SearchSymbols::symbolName(const Symbol *symbol) const
{
267 268 269 270 271 272 273 274
    QString symbolName = overview.prettyName(symbol->name());
    if (symbolName.isEmpty()) {
        QString type;
        if (symbol->isNamespace()) {
            type = QLatin1String("namespace");
        } else if (symbol->isEnum()) {
            type = QLatin1String("enum");
        } else if (const Class *c = symbol->asClass())  {
275
            if (c->isUnion())
276
                type = QLatin1String("union");
277
            else if (c->isStruct())
278
                type = QLatin1String("struct");
279
            else
280 281 282 283 284 285
                type = QLatin1String("class");
        } else {
            type = QLatin1String("symbol");
        }
        symbolName = QLatin1String("<anonymous ");
        symbolName += type;
286
        symbolName += QLatin1Char('>');
287
    }
288 289 290
    return symbolName;
}

291 292
void SearchSymbols::appendItem(const QString &symbolName, const QString &symbolType,
                               const QString &symbolScope, ModelItemInfo::ItemType itemType,
293
                               Symbol *symbol)
294
{
295 296 297
    if (!symbol->name())
        return;

298 299 300 301 302 303
    QString path = m_paths.value(symbol->fileId(), QString());
    if (path.isEmpty()) {
        path = QString::fromUtf8(symbol->fileName(), symbol->fileNameLength());
        m_paths.insert(symbol->fileId(), path);
    }

304
    const QIcon icon = icons.iconForSymbol(symbol);
305 306 307 308
    items.append(ModelItemInfo(findOrInsert(symbolName),
                               findOrInsert(symbolType),
                               findOrInsert(symbolScope),
                               itemType,
309
                               path,
310
                               symbol->line(),
311
                               symbol->column() - 1, // 1-based vs 0-based column
312
                               icon));
313
}