diff options
Diffstat (limited to 'src/libs/cplusplus')
-rw-r--r-- | src/libs/cplusplus/CppDocument.cpp | 41 | ||||
-rw-r--r-- | src/libs/cplusplus/CppRewriter.cpp | 186 | ||||
-rw-r--r-- | src/libs/cplusplus/CppRewriter.h | 5 | ||||
-rw-r--r-- | src/libs/cplusplus/LookupContext.cpp | 4 | ||||
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.cpp | 102 | ||||
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.h | 9 | ||||
-rw-r--r-- | src/libs/cplusplus/SnapshotSymbolVisitor.cpp | 60 | ||||
-rw-r--r-- | src/libs/cplusplus/SnapshotSymbolVisitor.h | 57 | ||||
-rw-r--r-- | src/libs/cplusplus/SymbolNameVisitor.cpp | 55 | ||||
-rw-r--r-- | src/libs/cplusplus/SymbolNameVisitor.h | 52 | ||||
-rw-r--r-- | src/libs/cplusplus/TypeOfExpression.cpp | 35 | ||||
-rw-r--r-- | src/libs/cplusplus/TypeOfExpression.h | 8 | ||||
-rw-r--r-- | src/libs/cplusplus/cplusplus-lib.pri | 4 | ||||
-rw-r--r-- | src/libs/cplusplus/cplusplus.pri | 4 |
14 files changed, 571 insertions, 51 deletions
diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index 53105fd5b4..ef159e9370 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -46,6 +46,9 @@ #include <AST.h> #include <Scope.h> #include <SymbolVisitor.h> +#include <NameVisitor.h> +#include <TypeVisitor.h> +#include <CoreTypes.h> #include <QtCore/QByteArray> #include <QtCore/QBitArray> @@ -691,11 +694,17 @@ namespace { class FindMatchingDefinition: public SymbolVisitor { Symbol *_declaration; + const OperatorNameId *_oper; QList<Function *> _result; public: FindMatchingDefinition(Symbol *declaration) - : _declaration(declaration) {} + : _declaration(declaration) + , _oper(0) + { + if (_declaration->name()) + _oper = _declaration->name()->asOperatorNameId(); + } QList<Function *> result() const { return _result; } @@ -703,8 +712,15 @@ public: virtual bool visit(Function *fun) { - if (_declaration->identifier()->isEqualTo(fun->identifier())) - _result.append(fun); + if (_oper) { + if (const Name *name = fun->unqualifiedName()) { + if (_oper->isEqualTo(name)) + _result.append(fun); + } + } else if (const Identifier *id = _declaration->identifier()) { + if (id->isEqualTo(fun->identifier())) + _result.append(fun); + } return false; } @@ -718,7 +734,7 @@ public: Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const { - if (! (declaration && declaration->identifier())) + if (!declaration) return 0; Document::Ptr thisDocument = document(QString::fromUtf8(declaration->fileName(), declaration->fileNameLength())); @@ -734,9 +750,19 @@ Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const } foreach (Document::Ptr doc, *this) { - if (! doc->control()->findIdentifier(declaration->identifier()->chars(), - declaration->identifier()->size())) + const Identifier *id = declaration->identifier(); + if (id && ! doc->control()->findIdentifier(id->chars(), + id->size())) continue; + if (!id) { + if (!declaration->name()) + continue; + const OperatorNameId *oper = declaration->name()->asOperatorNameId(); + if (!oper) + continue; + if (!doc->control()->findOperatorNameId(oper->kind())) + continue; + } FindMatchingDefinition candidates(declaration); candidates.accept(doc->globalNamespace()); @@ -770,9 +796,8 @@ Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const Function *best = 0; foreach (Function *fun, viableFunctions) { - if (fun->unqualifiedName()->isEqualTo(declaration->unqualifiedName())) + if (! (fun->unqualifiedName() && fun->unqualifiedName()->isEqualTo(declaration->unqualifiedName()))) continue; - else if (fun->argumentCount() == declarationTy->argumentCount()) { if (! best) best = fun; diff --git a/src/libs/cplusplus/CppRewriter.cpp b/src/libs/cplusplus/CppRewriter.cpp index 8c11c03a02..40b360abda 100644 --- a/src/libs/cplusplus/CppRewriter.cpp +++ b/src/libs/cplusplus/CppRewriter.cpp @@ -41,11 +41,12 @@ #include <Overview.h> #include <QtCore/QVarLengthArray> +#include <QtCore/QRegExp> #include <QtCore/QDebug> -using namespace CPlusPlus; +namespace CPlusPlus { -class CPlusPlus::Rewrite +class Rewrite { public: Rewrite(Control *control, SubstitutionEnvironment *env) @@ -418,18 +419,187 @@ FullySpecifiedType UseQualifiedNames::apply(const Name *name, Rewrite *rewrite) } -FullySpecifiedType CPlusPlus::rewriteType(const FullySpecifiedType &type, - SubstitutionEnvironment *env, - Control *control) +FullySpecifiedType rewriteType(const FullySpecifiedType &type, + SubstitutionEnvironment *env, + Control *control) { Rewrite rewrite(control, env); return rewrite.rewriteType(type); } -const Name *CPlusPlus::rewriteName(const Name *name, - SubstitutionEnvironment *env, - Control *control) +const Name *rewriteName(const Name *name, + SubstitutionEnvironment *env, + Control *control) { Rewrite rewrite(control, env); return rewrite.rewriteName(name); } + +// Simplify complicated STL template types, +// such as 'std::basic_string<char,std::char_traits<char>,std::allocator<char> >' +// -> 'std::string' and helpers. + +static QString chopConst(QString type) +{ + while (1) { + if (type.startsWith(QLatin1String("const"))) + type = type.mid(5); + else if (type.startsWith(QLatin1Char(' '))) + type = type.mid(1); + else if (type.endsWith(QLatin1String("const"))) + type.chop(5); + else if (type.endsWith(QLatin1Char(' '))) + type.chop(1); + else + break; + } + return type; +} + +static inline QRegExp stdStringRegExp(const QString &charType) +{ + QString rc = QLatin1String("basic_string<"); + rc += charType; + rc += QLatin1String(",[ ]?std::char_traits<"); + rc += charType; + rc += QLatin1String(">,[ ]?std::allocator<"); + rc += charType; + rc += QLatin1String("> >"); + const QRegExp re(rc); + Q_ASSERT(re.isValid()); + return re; +} + +// Simplify string types in a type +// 'std::set<std::basic_string<char... > >' -> std::set<std::string>' +static inline void simplifyStdString(const QString &charType, const QString &replacement, + QString *type) +{ + QRegExp stringRegexp = stdStringRegExp(charType); + const int replacementSize = replacement.size(); + for (int pos = 0; pos < type->size(); ) { + // Check next match + const int matchPos = stringRegexp.indexIn(*type, pos); + if (matchPos == -1) + break; + const int matchedLength = stringRegexp.matchedLength(); + type->replace(matchPos, matchedLength, replacement); + pos = matchPos + replacementSize; + // If we were inside an 'allocator<std::basic_string..char > >' + // kill the following blank -> 'allocator<std::string>' + if (pos + 1 < type->size() && type->at(pos) == QLatin1Char(' ') + && type->at(pos + 1) == QLatin1Char('>')) + type->remove(pos, 1); + } +} + +// Fix 'std::allocator<std::string >' -> 'std::allocator<std::string>', +// which can happen when replacing/simplifying +static inline QString fixNestedTemplates(QString s) +{ + const int size = s.size(); + if (size > 3 + && s.at(size - 1) == QLatin1Char('>') + && s.at(size - 2) == QLatin1Char(' ') + && s.at(size - 3) != QLatin1Char('>')) + s.remove(size - 2, 1); + return s; +} + +CPLUSPLUS_EXPORT QString simplifySTLType(const QString &typeIn) +{ + QString type = typeIn; + if (type.startsWith("class ")) // MSVC prepends class,struct + type.remove(0, 6); + if (type.startsWith("struct ")) + type.remove(0, 7); + + type.replace(QLatin1Char('*'), QLatin1Char('@')); + + for (int i = 0; i < 10; ++i) { + int start = type.indexOf("std::allocator<"); + if (start == -1) + break; + // search for matching '>' + int pos; + int level = 0; + for (pos = start + 12; pos < type.size(); ++pos) { + int c = type.at(pos).unicode(); + if (c == '<') { + ++level; + } else if (c == '>') { + --level; + if (level == 0) + break; + } + } + const QString alloc = fixNestedTemplates(type.mid(start, pos + 1 - start).trimmed()); + const QString inner = fixNestedTemplates(alloc.mid(15, alloc.size() - 16).trimmed()); + if (inner == QLatin1String("char")) { // std::string + simplifyStdString(QLatin1String("char"), QLatin1String("string"), &type); + } else if (inner == QLatin1String("wchar_t")) { // std::wstring + simplifyStdString(QLatin1String("wchar_t"), QLatin1String("wstring"), &type); + } else if (inner == QLatin1String("unsigned short")) { // std::wstring/MSVC + simplifyStdString(QLatin1String("unsigned short"), QLatin1String("wstring"), &type); + } + // std::vector, std::deque, std::list + const QRegExp re1(QString::fromLatin1("(vector|list|deque)<%1, ?%2\\s*>").arg(inner, alloc)); + Q_ASSERT(re1.isValid()); + if (re1.indexIn(type) != -1) + type.replace(re1.cap(0), QString::fromLatin1("%1<%2>").arg(re1.cap(1), inner)); + + // std::stack + QRegExp stackRE(QString::fromLatin1("stack<%1, ?std::deque<%2> >").arg(inner, inner)); + stackRE.setMinimal(true); + Q_ASSERT(stackRE.isValid()); + if (stackRE.indexIn(type) != -1) + type.replace(stackRE.cap(0), QString::fromLatin1("stack<%1>").arg(inner)); + + // std::set + QRegExp setRE(QString::fromLatin1("set<%1, ?std::less<%2>, ?%3\\s*>").arg(inner, inner, alloc)); + setRE.setMinimal(true); + Q_ASSERT(setRE.isValid()); + if (setRE.indexIn(type) != -1) + type.replace(setRE.cap(0), QString::fromLatin1("set<%1>").arg(inner)); + + // std::map + if (inner.startsWith("std::pair<")) { + // search for outermost ',', split key and value + int pos; + int level = 0; + for (pos = 10; pos < inner.size(); ++pos) { + int c = inner.at(pos).unicode(); + if (c == '<') + ++level; + else if (c == '>') + --level; + else if (c == ',' && level == 0) + break; + } + const QString key = chopConst(inner.mid(10, pos - 10)); + // Get value: MSVC: 'pair<a const ,b>', gcc: 'pair<const a, b>' + if (inner.at(++pos) == QLatin1Char(' ')) + pos++; + QString value = inner.mid(pos, inner.size() - pos - 1).trimmed(); + QRegExp mapRE1(QString("map<%1, ?%2, ?std::less<%3 ?>, ?%4\\s*>") + .arg(key, value, key, alloc)); + mapRE1.setMinimal(true); + Q_ASSERT(mapRE1.isValid()); + if (mapRE1.indexIn(type) != -1) { + type.replace(mapRE1.cap(0), QString("map<%1, %2>").arg(key, value)); + } else { + QRegExp mapRE2(QString("map<const %1, ?%2, ?std::less<const %3>, ?%4\\s*>") + .arg(key, value, key, alloc)); + mapRE2.setMinimal(true); + if (mapRE2.indexIn(type) != -1) { + type.replace(mapRE2.cap(0), QString("map<const %1, %2>").arg(key, value)); + } + } + } + } + type.replace(QLatin1Char('@'), QLatin1Char('*')); + type.replace(QLatin1String(" >"), QLatin1String(">")); + return type; +} + +} // namespace CPlusPlus diff --git a/src/libs/cplusplus/CppRewriter.h b/src/libs/cplusplus/CppRewriter.h index 93326ffee3..fa5264310c 100644 --- a/src/libs/cplusplus/CppRewriter.h +++ b/src/libs/cplusplus/CppRewriter.h @@ -108,6 +108,11 @@ CPLUSPLUS_EXPORT const Name *rewriteName(const Name *name, SubstitutionEnvironment *env, Control *control); +// Simplify complicated STL template types, such as +// 'std::basic_string<char,std::char_traits<char>,std::allocator<char> > '-> +// 'std::string'. +CPLUSPLUS_EXPORT QString simplifySTLType(const QString &typeIn); + } // end of namespace CPlusPlus #endif diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index d14413e5b5..cdf95bc9dc 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -460,6 +460,8 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding foreach (Symbol *s, binding->symbols()) { if (s->isFriend()) continue; + else if (s->isUsingNamespaceDirective()) + continue; if (Scope *scope = s->asScope()) { if (Class *klass = scope->asClass()) { @@ -513,6 +515,8 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope, for (Symbol *s = scope->find(id); s; s = s->next()) { if (s->isFriend()) continue; // skip friends + else if (s->isUsingNamespaceDirective()) + continue; // skip using namespace directives else if (! id->isEqualTo(s->identifier())) continue; else if (s->name()->isQualifiedNameId()) diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 890ee12c3d..cad552f923 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -79,7 +79,8 @@ ResolveExpression::ResolveExpression(const LookupContext &context) : ASTVisitor(context.expressionDocument()->translationUnit()), _scope(0), _context(context), - bind(context.expressionDocument()->translationUnit()) + bind(context.expressionDocument()->translationUnit()), + _reference(false) { } ResolveExpression::~ResolveExpression() @@ -88,19 +89,26 @@ ResolveExpression::~ResolveExpression() QList<LookupItem> ResolveExpression::operator()(ExpressionAST *ast, Scope *scope) { return resolve(ast, scope); } -QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast, Scope *scope) +QList<LookupItem> ResolveExpression::reference(ExpressionAST *ast, Scope *scope) +{ return resolve(ast, scope, true); } + +QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast, Scope *scope, bool ref) { if (! scope) return QList<LookupItem>(); - Scope *previousVisibleSymbol = _scope; - _scope = scope; - const QList<LookupItem> result = resolve(ast); - _scope = previousVisibleSymbol; + std::swap(_scope, scope); + std::swap(_reference, ref); + + const QList<LookupItem> result = expression(ast); + + std::swap(_reference, ref); + std::swap(_scope, scope); + return result; } -QList<LookupItem> ResolveExpression::resolve(ExpressionAST *ast) +QList<LookupItem> ResolveExpression::expression(ExpressionAST *ast) { const QList<LookupItem> previousResults = switchResults(QList<LookupItem>()); accept(ast); @@ -445,27 +453,18 @@ bool ResolveExpression::visit(ConversionFunctionIdAST *) return false; } -bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const +bool ResolveExpression::maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) { - unsigned minNumberArguments = 0; - - for (; minNumberArguments < funTy->argumentCount(); ++minNumberArguments) { - Argument *arg = funTy->argumentAt(minNumberArguments)->asArgument(); - - if (arg->hasInitializer()) - break; - } - - if (actualArgumentCount < minNumberArguments) { - // not enough arguments. - return false; - - } else if (! funTy->isVariadic() && actualArgumentCount > funTy->argumentCount()) { - // too many arguments. - return false; - } + return funTy->maybeValidPrototype(actualArgumentCount); +} - return true; +bool ResolveExpression::implicitConversion(const FullySpecifiedType &sourceTy, const FullySpecifiedType &targetTy) const +{ + if (sourceTy.isEqualTo(targetTy)) + return true; + else if (sourceTy.simplified().isEqualTo(targetTy.simplified())) + return true; + return false; } bool ResolveExpression::visit(CallAST *ast) @@ -473,14 +472,55 @@ bool ResolveExpression::visit(CallAST *ast) const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope); // Compute the types of the actual arguments. - int actualArgumentCount = 0; + unsigned actualArgumentCount = 0; - //QList< QList<Result> > arguments; + QList< QList<LookupItem> > arguments; for (ExpressionListAST *exprIt = ast->expression_list; exprIt; exprIt = exprIt->next) { - //arguments.append(resolve(exprIt->expression)); + if (_reference) + arguments.append(resolve(exprIt->value, _scope)); + ++actualArgumentCount; } + if (_reference) { + _results.clear(); + foreach (const LookupItem &base, baseResults) { + if (Function *funTy = base.type()->asFunctionType()) { + if (! maybeValidPrototype(funTy, actualArgumentCount)) + continue; + + int score = 0; + + for (unsigned i = 0; i < funTy->argumentCount(); ++i) { + const FullySpecifiedType formalTy = funTy->argumentAt(i)->type(); + + FullySpecifiedType actualTy; + if (i < unsigned(arguments.size())) { + const QList<LookupItem> actual = arguments.at(i); + if (actual.isEmpty()) + continue; + + actualTy = actual.first().type(); + } else + actualTy = formalTy; + + if (implicitConversion(actualTy, formalTy)) + ++score; + } + + if (score) + _results.prepend(base); + else + _results.append(base); + } + } + + if (_results.isEmpty()) + _results = baseResults; + + return false; + } + const Name *functionCallOp = control()->operatorNameId(OperatorNameId::FunctionCallOp); foreach (const LookupItem &result, baseResults) { @@ -517,7 +557,7 @@ bool ResolveExpression::visit(CallAST *ast) bool ResolveExpression::visit(ArrayAccessAST *ast) { const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope); - const QList<LookupItem> indexResults = resolve(ast->expression); + const QList<LookupItem> indexResults = resolve(ast->expression, _scope); const Name *arrayAccessOp = control()->operatorNameId(OperatorNameId::ArrayAccessOp); @@ -713,7 +753,7 @@ bool ResolveExpression::visit(PostIncrDecrAST *ast) bool ResolveExpression::visit(ObjCMessageExpressionAST *ast) { - const QList<LookupItem> receiverResults = resolve(ast->receiver_expression); + const QList<LookupItem> receiverResults = resolve(ast->receiver_expression, _scope); foreach (const LookupItem &result, receiverResults) { FullySpecifiedType ty = result.type().simplified(); diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index 49b79e9e38..1c0215462c 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -49,7 +49,8 @@ public: virtual ~ResolveExpression(); QList<LookupItem> operator()(ExpressionAST *ast, Scope *scope); - QList<LookupItem> resolve(ExpressionAST *ast, Scope *scope); + QList<LookupItem> resolve(ExpressionAST *ast, Scope *scope, bool ref = false); + QList<LookupItem> reference(ExpressionAST *ast, Scope *scope); ClassOrNamespace *baseExpression(const QList<LookupItem> &baseResults, int accessOp, @@ -60,7 +61,7 @@ public: protected: ClassOrNamespace *findClass(const FullySpecifiedType &ty, Scope *scope) const; - QList<LookupItem> resolve(ExpressionAST *ast); + QList<LookupItem> expression(ExpressionAST *ast); QList<LookupItem> switchResults(const QList<LookupItem> &symbols); FullySpecifiedType instantiate(const Name *className, Symbol *candidate) const; @@ -73,7 +74,8 @@ protected: void addResults(const QList<Symbol *> &symbols); void addResults(const QList<LookupItem> &items); - bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const; + static bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount); + bool implicitConversion(const FullySpecifiedType &sourceTy, const FullySpecifiedType &targetTy) const; using ASTVisitor::visit; @@ -123,6 +125,7 @@ private: LookupContext _context; Bind bind; QList<LookupItem> _results; + bool _reference; }; } // end of namespace CPlusPlus diff --git a/src/libs/cplusplus/SnapshotSymbolVisitor.cpp b/src/libs/cplusplus/SnapshotSymbolVisitor.cpp new file mode 100644 index 0000000000..7962d3f928 --- /dev/null +++ b/src/libs/cplusplus/SnapshotSymbolVisitor.cpp @@ -0,0 +1,60 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "SnapshotSymbolVisitor.h" +#include <Symbols.h> + +using namespace CPlusPlus; + +SnapshotSymbolVisitor::SnapshotSymbolVisitor(const Snapshot &snapshot) + : _snapshot(snapshot) +{ +} + +void SnapshotSymbolVisitor::accept(Document::Ptr doc) +{ + QSet<QString> processed; + accept(doc, &processed); +} + +void SnapshotSymbolVisitor::accept(Document::Ptr doc, QSet<QString> *processed) +{ + if (doc && doc->globalNamespace() && ! processed->contains(doc->fileName())) { + processed->insert(doc->fileName()); + + foreach (const Document::Include &i, doc->includes()) { + if (Document::Ptr incl = _snapshot.document(i.fileName())) + accept(incl, processed); + } + + std::swap(_document, doc); + accept(_document->globalNamespace()); + std::swap(_document, doc); + } +} diff --git a/src/libs/cplusplus/SnapshotSymbolVisitor.h b/src/libs/cplusplus/SnapshotSymbolVisitor.h new file mode 100644 index 0000000000..13d639aea1 --- /dev/null +++ b/src/libs/cplusplus/SnapshotSymbolVisitor.h @@ -0,0 +1,57 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef CPLUSPLUS_SNAPSHOTSYMBOLVISITOR_H +#define CPLUSPLUS_SNAPSHOTSYMBOLVISITOR_H + +#include "CppDocument.h" +#include <SymbolVisitor.h> +#include <QtCore/QSet> + +namespace CPlusPlus { + +class CPLUSPLUS_EXPORT SnapshotSymbolVisitor : public CPlusPlus::SymbolVisitor +{ +public: + SnapshotSymbolVisitor(const Snapshot &snapshot); + + void accept(Document::Ptr doc); + using SymbolVisitor::accept; + +protected: + void accept(Document::Ptr doc, QSet<QString> *processed); + +private: + Snapshot _snapshot; + Document::Ptr _document; +}; + +} // end of namespace CPlusPlus + +#endif // CPLUSPLUS_SNAPSHOTSYMBOLVISITOR_H diff --git a/src/libs/cplusplus/SymbolNameVisitor.cpp b/src/libs/cplusplus/SymbolNameVisitor.cpp new file mode 100644 index 0000000000..c384e36dcd --- /dev/null +++ b/src/libs/cplusplus/SymbolNameVisitor.cpp @@ -0,0 +1,55 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "SymbolNameVisitor.h" +#include <Symbols.h> +#include <Names.h> + +using namespace CPlusPlus; + +SymbolNameVisitor::SymbolNameVisitor() + : _symbol(0) +{ +} + +void SymbolNameVisitor::accept(Symbol *symbol) +{ + if (symbol) { + if (Scope *scope = symbol->enclosingScope()) + accept(scope); + + if (! symbol->isTemplate()) { + if (const Name *name = symbol->name()) { + std::swap(_symbol, symbol); + accept(name); + std::swap(_symbol, symbol); + } + } + } +} diff --git a/src/libs/cplusplus/SymbolNameVisitor.h b/src/libs/cplusplus/SymbolNameVisitor.h new file mode 100644 index 0000000000..8b41be18c9 --- /dev/null +++ b/src/libs/cplusplus/SymbolNameVisitor.h @@ -0,0 +1,52 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef CPLUSPLUS_SYMBOLNAMEVISITOR_H +#define CPLUSPLUS_SYMBOLNAMEVISITOR_H + +#include <NameVisitor.h> + +namespace CPlusPlus { + +class CPLUSPLUS_EXPORT SymbolNameVisitor : public CPlusPlus::NameVisitor +{ +public: + SymbolNameVisitor(); + + void accept(Symbol *symbol); + + using NameVisitor::accept; + +private: + Symbol *_symbol; +}; + +} // end of namespace CPlusPlus + +#endif // CPLUSPLUS_SYMBOLNAMEVISITOR_H diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp index adf84ae41d..7a268c4402 100644 --- a/src/libs/cplusplus/TypeOfExpression.cpp +++ b/src/libs/cplusplus/TypeOfExpression.cpp @@ -88,6 +88,20 @@ QList<LookupItem> TypeOfExpression::operator()(const QString &expression, scope); } +QList<LookupItem> TypeOfExpression::reference(const QString &expression, + Scope *scope, + PreprocessMode mode) +{ + QString code = expression; + + if (mode == Preprocess) + code = preprocessedExpression(expression); + + Document::Ptr expressionDoc = documentForExpression(code); + expressionDoc->check(); + return reference(extractExpressionAST(expressionDoc), expressionDoc, scope); +} + QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression, Document::Ptr document, Scope *scope) @@ -108,6 +122,26 @@ QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression, return items; } +QList<LookupItem> TypeOfExpression::reference(ExpressionAST *expression, + Document::Ptr document, + Scope *scope) +{ + m_ast = expression; + + m_scope = scope; + + m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot); + m_lookupContext.setBindings(m_bindings); + + ResolveExpression resolve(m_lookupContext); + const QList<LookupItem> items = resolve.reference(m_ast, scope); + + if (! m_bindings) + m_lookupContext = resolve.context(); + + return items; +} + QString TypeOfExpression::preprocess(const QString &expression) const { return preprocessedExpression(expression); @@ -183,3 +217,4 @@ QString TypeOfExpression::preprocessedExpression(const QString &expression) cons const QByteArray preprocessedCode = preproc("<expression>", code); return QString::fromUtf8(preprocessedCode.constData(), preprocessedCode.size()); } + diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h index 6ca59f690e..4852baa152 100644 --- a/src/libs/cplusplus/TypeOfExpression.h +++ b/src/libs/cplusplus/TypeOfExpression.h @@ -102,6 +102,14 @@ public: Document::Ptr document, Scope *scope); + QList<LookupItem> reference(const QString &expression, + Scope *scope, + PreprocessMode mode = NoPreprocess); + + QList<LookupItem> reference(ExpressionAST *expression, + Document::Ptr document, + Scope *scope); + QString preprocess(const QString &expression) const; /** diff --git a/src/libs/cplusplus/cplusplus-lib.pri b/src/libs/cplusplus/cplusplus-lib.pri index 2a718d5712..395636a23c 100644 --- a/src/libs/cplusplus/cplusplus-lib.pri +++ b/src/libs/cplusplus/cplusplus-lib.pri @@ -37,6 +37,8 @@ HEADERS += \ $$PWD/LookupContext.h \ $$PWD/ASTParent.h \ $$PWD/ASTPath.h \ + $$PWD/SnapshotSymbolVisitor.h \ + $$PWD/SymbolNameVisitor.h \ $$PWD/DeprecatedGenTemplateInstance.h \ $$PWD/FindUsages.h \ $$PWD/DependencyTable.h \ @@ -63,6 +65,8 @@ SOURCES += \ $$PWD/LookupContext.cpp \ $$PWD/ASTParent.cpp \ $$PWD/ASTPath.cpp \ + $$PWD/SnapshotSymbolVisitor.cpp \ + $$PWD/SymbolNameVisitor.cpp \ $$PWD/DeprecatedGenTemplateInstance.cpp \ $$PWD/FindUsages.cpp \ $$PWD/DependencyTable.cpp \ diff --git a/src/libs/cplusplus/cplusplus.pri b/src/libs/cplusplus/cplusplus.pri index 50a03111e9..85cb972095 100644 --- a/src/libs/cplusplus/cplusplus.pri +++ b/src/libs/cplusplus/cplusplus.pri @@ -1,3 +1,5 @@ INCLUDEPATH += $$IDE_SOURCE_TREE/src/shared/cplusplus DEPENDPATH += $$IDE_SOURCE_TREE/src/shared/cplusplus -LIBS *= -l$$qtLibraryTarget(CPlusPlus) +INCLUDEPATH += $$IDE_SOURCE_TREE/src/libs/cplusplus +DEPENDPATH += $$IDE_SOURCE_TREE/src/libs/cplusplus +LIBS *= -l$$qtLibraryName(CPlusPlus) |