diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp index ae677bcdb69b34885009ff9c41e97a6b17a63710..7746670f381edef376d3696c6e5571a7d1c92888 100644 --- a/share/qtcreator/gdbmacros/gdbmacros.cpp +++ b/share/qtcreator/gdbmacros/gdbmacros.cpp @@ -57,6 +57,12 @@ #include <QtCore/QTextStream> #include <QtCore/QVector> +#if (QT_POINTER_SIZE==4) // How to printf/scanf a pointer (uintptr_t) +# define POINTER_PRINTFORMAT "0x%x" +#else +# define POINTER_PRINTFORMAT "0x%lx" +#endif + #ifndef QT_BOOTSTRAPPED #include <QtCore/QModelIndex> @@ -630,18 +636,10 @@ QDumper &QDumper::put(int i) QDumper &QDumper::put(const void *p) { - static char buf[100]; if (p) { - sprintf(buf, "%p", p); - // we get a '0x' prefix only on some implementations. - // if it isn't there, write it out manually. - if (buf[1] != 'x') { - put('0'); - put('x'); - } - put(buf); + pos += sprintf(outBuffer + pos, POINTER_PRINTFORMAT, reinterpret_cast<uintptr_t>(p)); } else { - put("<null>"); + pos += sprintf(outBuffer + pos, "<null>"); } return *this; } @@ -1070,7 +1068,10 @@ static void qDumpQAbstractItem(QDumper &d) QModelIndex mi; { ModelIndex *mm = reinterpret_cast<ModelIndex *>(&mi); - sscanf(d.templateParameters[0], "%d,%d,%p,%p", &mm->r, &mm->c, &mm->p, &mm->m); + mm->r = mm->c = 0; + mm->p = mm->m = 0; + sscanf(d.templateParameters[0], "%d,%d,"POINTER_PRINTFORMAT","POINTER_PRINTFORMAT, &mm->r, &mm->c, + reinterpret_cast<uintptr_t*>(&mm->p), reinterpret_cast<uintptr_t*>(&mm->m)); } const QAbstractItemModel *m = mi.model(); const int rowCount = m->rowCount(mi); @@ -2149,8 +2150,8 @@ static void qDumpQVariantHelper(const QVariant *v, QString *value, default: { char buf[1000]; const char *format = (v->typeName()[0] == 'Q') - ? "'"NS"%s "NS"qVariantValue<"NS"%s >'(*('"NS"QVariant'*)%p)" - : "'%s "NS"qVariantValue<%s >'(*('"NS"QVariant'*)%p)"; + ? "'"NS"%s "NS"qVariantValue<"NS"%s >'(*('"NS"QVariant'*)"POINTER_PRINTFORMAT")" + : "'%s "NS"qVariantValue<%s >'(*('"NS"QVariant'*)"POINTER_PRINTFORMAT")"; qsnprintf(buf, sizeof(buf) - 1, format, v->typeName(), v->typeName(), v); *exp = QLatin1String(buf); *numchild = 1; @@ -2925,7 +2926,7 @@ static void qDumpQVector(QDumper &d) if (innerIsPointerType && nn > 0) for (int i = 0; i != n; ++i) if (const void *p = addOffset(v, i * innersize + typeddatasize)) - qCheckAccess(deref(p)); + qCheckPointer(deref(p)); d.putItemCount("value", n); d.putItem("valueeditable", "false"); @@ -3590,10 +3591,16 @@ static void handleProtocolVersion2and3(QDumper &d) break; case 'V': #ifndef QT_BOOTSTRAPPED - if (isEqual(type, "QVariant")) + if (isEqual(type, "QVariantList")) { // resolve typedef + d.outerType = "QList"; + d.innerType = "QVariant"; + d.extraInt[0] = sizeof(QVariant); + qDumpQList(d); + } else if (isEqual(type, "QVariant")) { qDumpQVariant(d); - else if (isEqual(type, "QVector")) + } else if (isEqual(type, "QVector")) { qDumpQVector(d); + } #endif break; case 'W': @@ -3801,6 +3808,7 @@ void *qDumpObjectData440( "\""NS"QStringList\"," "\""NS"QTextCodec\"," "\""NS"QVariant\"," + "\""NS"QVariantList\"," "\""NS"QVector\"," #if QT_VERSION >= 0x040500 "\""NS"QMultiMap\"," diff --git a/share/qtcreator/gdbmacros/test/main.cpp b/share/qtcreator/gdbmacros/test/main.cpp index 60e0989294b9055bb13baf75b424c76723b450b5..de8fc9f91f209a3c41137d081995825a9dc6a911 100644 --- a/share/qtcreator/gdbmacros/test/main.cpp +++ b/share/qtcreator/gdbmacros/test/main.cpp @@ -280,6 +280,27 @@ static int dumpQVariant() return 0; } +static int dumpQVariantList() +{ + QVariantList test; + if (!optEmptyContainers) { + test.push_back(QVariant(QLatin1String("hallo"))); + test.push_back(QVariant(42)); + test.push_back(QVariant(3.141)); + } + // As a list + prepareInBuffer("QList", "local.qvariantlist", "local.qvariantlist", "QVariant"); + qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(QVariant), 0,0 ,0); + fputs(qDumpOutBuffer, stdout); + // As typedef + fputs("\n\n", stdout); + prepareInBuffer("QVariantList", "local.qvariantlist", "local.qvariantlist", ""); + qDumpObjectData440(2, 42, testAddress(&test), 1, 0, 0,0 ,0); + fputs(qDumpOutBuffer, stdout); + fputc('\n', stdout); + return 0; +} + // --------------- std types static int dumpStdString() @@ -548,6 +569,7 @@ static TypeDumpFunctionMap registerTypes() rc.insert("QObject", dumpQObject); rc.insert("QObjectList", dumpQObjectList); rc.insert("QVariant", dumpQVariant); + rc.insert("QVariantList", dumpQVariantList); return rc; } diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp new file mode 100644 index 0000000000000000000000000000000000000000..46f98920f738dedd22ec24b1573f571977a58cda --- /dev/null +++ b/src/libs/cplusplus/FindUsages.cpp @@ -0,0 +1,446 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 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 "FindUsages.h" +#include "TypeOfExpression.h" + +#include <Control.h> +#include <Literals.h> +#include <Names.h> +#include <Symbols.h> +#include <AST.h> + +#include <QtCore/QDir> + +using namespace CPlusPlus; + +FindUsages::FindUsages(Document::Ptr doc, const Snapshot &snapshot, QFutureInterface<Usage> *future) + : ASTVisitor(doc->control()), + _future(future), + _doc(doc), + _snapshot(snapshot), + _source(_doc->source()), + _sem(doc->control()), + _inSimpleDeclaration(0) +{ + _snapshot.insert(_doc); +} + +void FindUsages::setGlobalNamespaceBinding(NamespaceBindingPtr globalNamespaceBinding) +{ + _globalNamespaceBinding = globalNamespaceBinding; +} + +QList<int> FindUsages::operator()(Symbol *symbol, Identifier *id, AST *ast) +{ + _references.clear(); + _declSymbol = symbol; + _id = id; + _exprDoc = Document::create("<references>"); + accept(ast); + return _references; +} + +QString FindUsages::matchingLine(const Token &tk) const +{ + const char *beg = _source.constData(); + const char *cp = beg + tk.offset; + for (; cp != beg - 1; --cp) { + if (*cp == '\n') + break; + } + + ++cp; + + const char *lineEnd = cp + 1; + for (; *lineEnd; ++lineEnd) { + if (*lineEnd == '\n') + break; + } + + const QString matchingLine = QString::fromUtf8(cp, lineEnd - cp); + return matchingLine; +} + +void FindUsages::reportResult(unsigned tokenIndex, const QList<Symbol *> &candidates) +{ + const bool isStrongResult = checkCandidates(candidates); + + if (isStrongResult) + reportResult(tokenIndex); +} + +void FindUsages::reportResult(unsigned tokenIndex) +{ + const Token &tk = tokenAt(tokenIndex); + const QString lineText = matchingLine(tk); + + unsigned line, col; + getTokenStartPosition(tokenIndex, &line, &col); + + if (col) + --col; // adjust the column position. + + const int len = tk.f.length; + + if (_future) { + const QString path = QDir::toNativeSeparators(_doc->fileName()); + _future->reportResult(Usage(path, line, lineText, col, len)); + } + + _references.append(tokenIndex); +} + +bool FindUsages::checkCandidates(const QList<Symbol *> &candidates) const +{ + if (Symbol *canonicalSymbol = LookupContext::canonicalSymbol(candidates, _globalNamespaceBinding.data())) { + +#if 0 + Symbol *c = candidates.first(); + qDebug() << "*** canonical symbol:" << canonicalSymbol->fileName() + << canonicalSymbol->line() << canonicalSymbol->column() + << "candidates:" << candidates.size() + << c->fileName() << c->line() << c->column(); +#endif + + return checkSymbol(canonicalSymbol); + } + + return false; +} + +bool FindUsages::checkScope(Symbol *symbol, Symbol *otherSymbol) const +{ + if (! (symbol && otherSymbol)) + return false; + + else if (symbol->scope() == otherSymbol->scope()) + return true; + + else if (symbol->name() && otherSymbol->name()) { + + if (! symbol->name()->isEqualTo(otherSymbol->name())) + return false; + + } else if (symbol->name() != otherSymbol->name()) { + return false; + } + + return checkScope(symbol->enclosingSymbol(), otherSymbol->enclosingSymbol()); +} + +bool FindUsages::checkSymbol(Symbol *symbol) const +{ + if (! symbol) { + return false; + + } else if (symbol == _declSymbol) { + return true; + + } else if (symbol->line() == _declSymbol->line() && symbol->column() == _declSymbol->column()) { + if (! qstrcmp(symbol->fileName(), _declSymbol->fileName())) + return true; + + } else if (symbol->isForwardClassDeclaration() && (_declSymbol->isClass() || + _declSymbol->isForwardClassDeclaration())) { + return checkScope(symbol, _declSymbol); + + } else if (_declSymbol->isForwardClassDeclaration() && (symbol->isClass() || + symbol->isForwardClassDeclaration())) { + return checkScope(symbol, _declSymbol); + } + + return false; +} + +LookupContext FindUsages::currentContext(AST *ast) +{ + unsigned line, column; + getTokenStartPosition(ast->firstToken(), &line, &column); + Symbol *lastVisibleSymbol = _doc->findSymbolAt(line, column); + + if (lastVisibleSymbol && lastVisibleSymbol == _previousContext.symbol()) + return _previousContext; + + LookupContext ctx(lastVisibleSymbol, _exprDoc, _doc, _snapshot); + _previousContext = ctx; + return ctx; +} + +void FindUsages::ensureNameIsValid(NameAST *ast) +{ + if (ast && ! ast->name) + ast->name = _sem.check(ast, /*scope = */ 0); +} + +bool FindUsages::visit(MemInitializerAST *ast) +{ + if (ast->name && ast->name->asSimpleName() != 0) { + ensureNameIsValid(ast->name); + + SimpleNameAST *simple = ast->name->asSimpleName(); + if (identifier(simple->identifier_token) == _id) { + LookupContext context = currentContext(ast); + const QList<Symbol *> candidates = context.resolve(simple->name); + reportResult(simple->identifier_token, candidates); + } + } + accept(ast->expression); + return false; +} + +bool FindUsages::visit(PostfixExpressionAST *ast) +{ + _postfixExpressionStack.append(ast); + return true; +} + +void FindUsages::endVisit(PostfixExpressionAST *) +{ + _postfixExpressionStack.removeLast(); +} + +bool FindUsages::visit(MemberAccessAST *ast) +{ + if (ast->member_name) { + if (SimpleNameAST *simple = ast->member_name->asSimpleName()) { + if (identifier(simple->identifier_token) == _id) { + Q_ASSERT(! _postfixExpressionStack.isEmpty()); + + checkExpression(_postfixExpressionStack.last()->firstToken(), + simple->identifier_token); + + return false; + } + } + } + + return true; +} + +void FindUsages::checkExpression(unsigned startToken, unsigned endToken) +{ + const unsigned begin = tokenAt(startToken).begin(); + const unsigned end = tokenAt(endToken).end(); + + const QString expression = _source.mid(begin, end - begin); + // qDebug() << "*** check expression:" << expression; + + TypeOfExpression typeofExpression; + typeofExpression.setSnapshot(_snapshot); + + unsigned line, column; + getTokenStartPosition(startToken, &line, &column); + Symbol *lastVisibleSymbol = _doc->findSymbolAt(line, column); + + const QList<TypeOfExpression::Result> results = + typeofExpression(expression, _doc, lastVisibleSymbol, + TypeOfExpression::Preprocess); + + QList<Symbol *> candidates; + + foreach (TypeOfExpression::Result r, results) { + FullySpecifiedType ty = r.first; + Symbol *lastVisibleSymbol = r.second; + + candidates.append(lastVisibleSymbol); + } + + reportResult(endToken, candidates); +} + +bool FindUsages::visit(QualifiedNameAST *ast) +{ + for (NestedNameSpecifierAST *nested_name_specifier = ast->nested_name_specifier; + nested_name_specifier; nested_name_specifier = nested_name_specifier->next) { + + if (NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name) { + SimpleNameAST *simple_name = class_or_namespace_name->asSimpleName(); + + TemplateIdAST *template_id = 0; + if (! simple_name) { + template_id = class_or_namespace_name->asTemplateId(); + + if (template_id) { + for (TemplateArgumentListAST *template_arguments = template_id->template_arguments; + template_arguments; template_arguments = template_arguments->next) { + accept(template_arguments->template_argument); + } + } + } + + if (simple_name || template_id) { + const unsigned identifier_token = simple_name + ? simple_name->identifier_token + : template_id->identifier_token; + + if (identifier(identifier_token) == _id) + checkExpression(ast->firstToken(), identifier_token); + } + } + } + + if (NameAST *unqualified_name = ast->unqualified_name) { + unsigned identifier_token = 0; + + if (SimpleNameAST *simple_name = unqualified_name->asSimpleName()) + identifier_token = simple_name->identifier_token; + + else if (DestructorNameAST *dtor_name = unqualified_name->asDestructorName()) + identifier_token = dtor_name->identifier_token; + + TemplateIdAST *template_id = 0; + if (! identifier_token) { + template_id = unqualified_name->asTemplateId(); + + if (template_id) { + identifier_token = template_id->identifier_token; + + for (TemplateArgumentListAST *template_arguments = template_id->template_arguments; + template_arguments; template_arguments = template_arguments->next) { + accept(template_arguments->template_argument); + } + } + } + + if (identifier_token && identifier(identifier_token) == _id) + checkExpression(ast->firstToken(), identifier_token); + } + + return false; +} + +bool FindUsages::visit(EnumeratorAST *ast) +{ + Identifier *id = identifier(ast->identifier_token); + if (id == _id) { + LookupContext context = currentContext(ast); + const QList<Symbol *> candidates = context.resolve(control()->nameId(id)); + reportResult(ast->identifier_token, candidates); + } + + accept(ast->expression); + + return false; +} + +bool FindUsages::visit(SimpleNameAST *ast) +{ + Identifier *id = identifier(ast->identifier_token); + if (id == _id) { + LookupContext context = currentContext(ast); + const QList<Symbol *> candidates = context.resolve(ast->name); + reportResult(ast->identifier_token, candidates); + } + + return false; +} + +bool FindUsages::visit(DestructorNameAST *ast) +{ + Identifier *id = identifier(ast->identifier_token); + if (id == _id) { + LookupContext context = currentContext(ast); + const QList<Symbol *> candidates = context.resolve(ast->name); + reportResult(ast->identifier_token, candidates); + } + + return false; +} + +bool FindUsages::visit(TemplateIdAST *ast) +{ + if (_id == identifier(ast->identifier_token)) { + LookupContext context = currentContext(ast); + const QList<Symbol *> candidates = context.resolve(ast->name); + reportResult(ast->identifier_token, candidates); + } + + for (TemplateArgumentListAST *template_arguments = ast->template_arguments; + template_arguments; template_arguments = template_arguments->next) { + accept(template_arguments->template_argument); + } + + return false; +} + +bool FindUsages::visit(ParameterDeclarationAST *ast) +{ + for (SpecifierAST *spec = ast->type_specifier; spec; spec = spec->next) + accept(spec); + + if (DeclaratorAST *declarator = ast->declarator) { + for (SpecifierAST *attr = declarator->attributes; attr; attr = attr->next) + accept(attr); + + for (PtrOperatorAST *ptr_op = declarator->ptr_operators; ptr_op; ptr_op = ptr_op->next) + accept(ptr_op); + + if (! _inSimpleDeclaration) // visit the core declarator only if we are not in simple-declaration. + accept(declarator->core_declarator); + + for (PostfixDeclaratorAST *fx_op = declarator->postfix_declarators; fx_op; fx_op = fx_op->next) + accept(fx_op); + + for (SpecifierAST *spec = declarator->post_attributes; spec; spec = spec->next) + accept(spec); + + accept(declarator->initializer); + } + + accept(ast->expression); + return false; +} + +bool FindUsages::visit(ExpressionOrDeclarationStatementAST *ast) +{ + accept(ast->declaration); + return false; +} + +bool FindUsages::visit(FunctionDeclaratorAST *ast) +{ + accept(ast->parameters); + + for (SpecifierAST *spec = ast->cv_qualifier_seq; spec; spec = spec->next) + accept(spec); + + accept(ast->exception_specification); + + return false; +} + +bool FindUsages::visit(SimpleDeclarationAST *) +{ + ++_inSimpleDeclaration; + return true; +} + +void FindUsages::endVisit(SimpleDeclarationAST *) +{ --_inSimpleDeclaration; } diff --git a/src/libs/cplusplus/FindUsages.h b/src/libs/cplusplus/FindUsages.h new file mode 100644 index 0000000000000000000000000000000000000000..9f82949380677777434fb57ec4a8b9e52b7ee5d2 --- /dev/null +++ b/src/libs/cplusplus/FindUsages.h @@ -0,0 +1,121 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 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 FINDUSAGES_H +#define FINDUSAGES_H + +#include "LookupContext.h" +#include "CppDocument.h" +#include "CppBindings.h" +#include "Semantic.h" + +#include <ASTVisitor.h> +#include <QtCore/QFutureInterface> + +namespace CPlusPlus { + +class CPLUSPLUS_EXPORT Usage +{ +public: + Usage() + : line(0), col(0), len(0) {} + + Usage(const QString &path, int line, const QString &lineText, int col, int len) + : path(path), line(line), lineText(lineText), col(col), len(len) {} + +public: + QString path; + int line; + QString lineText; + int col; + int len; +}; + +class CPLUSPLUS_EXPORT FindUsages: protected ASTVisitor +{ +public: + FindUsages(Document::Ptr doc, const Snapshot &snapshot, QFutureInterface<Usage> *future); + + void setGlobalNamespaceBinding(NamespaceBindingPtr globalNamespaceBinding); + + QList<int> operator()(Symbol *symbol, Identifier *id, AST *ast); + +protected: + using ASTVisitor::visit; + using ASTVisitor::endVisit; + + QString matchingLine(const Token &tk) const; + + void reportResult(unsigned tokenIndex, const QList<Symbol *> &candidates); + void reportResult(unsigned tokenIndex); + + bool checkSymbol(Symbol *symbol) const; + bool checkCandidates(const QList<Symbol *> &candidates) const; + bool checkScope(Symbol *symbol, Symbol *otherSymbol) const; + void checkExpression(unsigned startToken, unsigned endToken); + + LookupContext currentContext(AST *ast); + + void ensureNameIsValid(NameAST *ast); + + virtual bool visit(MemInitializerAST *ast); + virtual bool visit(PostfixExpressionAST *ast); + virtual void endVisit(PostfixExpressionAST *); + virtual bool visit(MemberAccessAST *ast); + virtual bool visit(QualifiedNameAST *ast); + virtual bool visit(EnumeratorAST *ast); + virtual bool visit(SimpleNameAST *ast); + virtual bool visit(DestructorNameAST *ast); + virtual bool visit(TemplateIdAST *ast); + virtual bool visit(ParameterDeclarationAST *ast); + virtual bool visit(ExpressionOrDeclarationStatementAST *ast); + virtual bool visit(FunctionDeclaratorAST *ast); + virtual bool visit(SimpleDeclarationAST *); + virtual void endVisit(SimpleDeclarationAST *); + +private: + QFutureInterface<Usage> *_future; + Identifier *_id; + Symbol *_declSymbol; + Document::Ptr _doc; + Snapshot _snapshot; + QByteArray _source; + Document::Ptr _exprDoc; + Semantic _sem; + NamespaceBindingPtr _globalNamespaceBinding; + QList<PostfixExpressionAST *> _postfixExpressionStack; + QList<QualifiedNameAST *> _qualifiedNameStack; + QList<int> _references; + LookupContext _previousContext; + int _inSimpleDeclaration; +}; + +} // end of namespace CPlusPlus + +#endif // FINDUSAGES_H diff --git a/src/libs/cplusplus/GenTemplateInstance.cpp b/src/libs/cplusplus/GenTemplateInstance.cpp index 07555932505a659c2069f01cbddc01d0c485e50c..0267efeefa8e165a530f90a5a11f676e684b573f 100644 --- a/src/libs/cplusplus/GenTemplateInstance.cpp +++ b/src/libs/cplusplus/GenTemplateInstance.cpp @@ -1,145 +1,377 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 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 "GenTemplateInstance.h" +#include "Overview.h" + #include <Control.h> #include <Scope.h> #include <Names.h> #include <Symbols.h> #include <CoreTypes.h> +#include <Literals.h> + #include <QtCore/QVarLengthArray> +#include <QtCore/QDebug> using namespace CPlusPlus; -GenTemplateInstance::GenTemplateInstance(Control *control, const Substitution &substitution) - : _control(control), - _substitution(substitution) -{ } - -FullySpecifiedType GenTemplateInstance::operator()(const FullySpecifiedType &ty) -{ return subst(ty); } +namespace { -FullySpecifiedType GenTemplateInstance::subst(Name *name) +class ApplySubstitution { - if (TemplateNameId *t = name->asTemplateNameId()) { - QVarLengthArray<FullySpecifiedType, 8> args(t->templateArgumentCount()); - - for (unsigned i = 0; i < t->templateArgumentCount(); ++i) - args[i] = subst(t->templateArgumentAt(i)); - - TemplateNameId *n = _control->templateNameId(t->identifier(), - args.data(), args.size()); - - return FullySpecifiedType(_control->namedType(n)); - } else if (name->isQualifiedNameId()) { - // ### implement me - } - - for (int i = 0; i < _substitution.size(); ++i) { - const QPair<Name *, FullySpecifiedType> s = _substitution.at(i); - if (name->isEqualTo(s.first)) - return s.second; - } - - return FullySpecifiedType(_control->namedType(name)); -} +public: + ApplySubstitution(const LookupContext &context, Symbol *symbol, const GenTemplateInstance::Substitution &substitution); + ~ApplySubstitution(); + + Control *control() const { return context.control(); } + + FullySpecifiedType apply(Name *name); + FullySpecifiedType apply(const FullySpecifiedType &type); + + int findSubstitution(Identifier *id) const; + FullySpecifiedType applySubstitution(int index) const; + +private: + class ApplyToType: protected TypeVisitor + { + public: + ApplyToType(ApplySubstitution *q) + : q(q) {} + + FullySpecifiedType operator()(const FullySpecifiedType &ty) + { + FullySpecifiedType previousType = switchType(ty); + accept(ty.type()); + return switchType(previousType); + } + + protected: + using TypeVisitor::visit; + + Control *control() const + { return q->control(); } + + FullySpecifiedType switchType(const FullySpecifiedType &type) + { + FullySpecifiedType previousType = _type; + _type = type; + return previousType; + } + + virtual void visit(VoidType *) + { + // nothing to do + } + + virtual void visit(IntegerType *) + { + // nothing to do + } + + virtual void visit(FloatType *) + { + // nothing to do + } + + virtual void visit(PointerToMemberType *) + { + qDebug() << Q_FUNC_INFO; // ### TODO + } + + virtual void visit(PointerType *ptrTy) + { + _type.setType(control()->pointerType(q->apply(ptrTy->elementType()))); + } + + virtual void visit(ReferenceType *refTy) + { + _type.setType(control()->referenceType(q->apply(refTy->elementType()))); + } + + virtual void visit(ArrayType *arrayTy) + { + _type.setType(control()->arrayType(q->apply(arrayTy->elementType()), arrayTy->size())); + } + + virtual void visit(NamedType *ty) + { + FullySpecifiedType n = q->apply(ty->name()); + _type.setType(n.type()); + } + + virtual void visit(Function *funTy) + { + Function *fun = control()->newFunction(/*sourceLocation=*/ 0, funTy->name()); + fun->setScope(funTy->scope()); + fun->setConst(funTy->isConst()); + fun->setVolatile(funTy->isVolatile()); + fun->setVirtual(funTy->isVirtual()); + fun->setAmbiguous(funTy->isAmbiguous()); + fun->setVariadic(funTy->isVariadic()); + + fun->setReturnType(q->apply(funTy->returnType())); + + for (unsigned i = 0; i < funTy->argumentCount(); ++i) { + Argument *originalArgument = funTy->argumentAt(i)->asArgument(); + Argument *arg = control()->newArgument(/*sourceLocation*/ 0, + originalArgument->name()); + + arg->setType(q->apply(originalArgument->type())); + arg->setInitializer(originalArgument->hasInitializer()); + fun->arguments()->enterSymbol(arg); + } + + _type.setType(fun); + } + + virtual void visit(Namespace *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(Class *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(Enum *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(ForwardClassDeclaration *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(ObjCClass *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(ObjCProtocol *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(ObjCMethod *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(ObjCForwardClassDeclaration *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(ObjCForwardProtocolDeclaration *) + { + qDebug() << Q_FUNC_INFO; + } + + private: + ApplySubstitution *q; + FullySpecifiedType _type; + QHash<Symbol *, FullySpecifiedType> _processed; + }; + + class ApplyToName: protected NameVisitor + { + public: + ApplyToName(ApplySubstitution *q): q(q) {} + + FullySpecifiedType operator()(Name *name) + { + FullySpecifiedType previousType = switchType(FullySpecifiedType()); + accept(name); + return switchType(previousType); + } + + protected: + Control *control() const + { return q->control(); } + + int findSubstitution(Identifier *id) const + { return q->findSubstitution(id); } + + FullySpecifiedType applySubstitution(int index) const + { return q->applySubstitution(index); } + + FullySpecifiedType switchType(const FullySpecifiedType &type) + { + FullySpecifiedType previousType = _type; + _type = type; + return previousType; + } + + virtual void visit(NameId *name) + { + int index = findSubstitution(name->identifier()); + + if (index != -1) + _type = applySubstitution(index); + + else + _type = control()->namedType(name); + } + + virtual void visit(TemplateNameId *name) + { + QVarLengthArray<FullySpecifiedType, 8> arguments(name->templateArgumentCount()); + for (unsigned i = 0; i < name->templateArgumentCount(); ++i) { + FullySpecifiedType argTy = name->templateArgumentAt(i); + arguments[i] = q->apply(argTy); + } + + TemplateNameId *templId = control()->templateNameId(name->identifier(), arguments.data(), arguments.size()); + _type = control()->namedType(templId); + } + + virtual void visit(QualifiedNameId *name) + { + QVarLengthArray<Name *, 8> names(name->nameCount()); + for (unsigned i = 0; i < name->nameCount(); ++i) { + Name *n = name->nameAt(i); + + if (TemplateNameId *templId = n->asTemplateNameId()) { + QVarLengthArray<FullySpecifiedType, 8> arguments(templId->templateArgumentCount()); + for (unsigned templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount(); ++templateArgIndex) { + FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex); + arguments[templateArgIndex] = q->apply(argTy); + } + + n = control()->templateNameId(templId->identifier(), arguments.data(), arguments.size()); + } + + names[i] = n; + } + + QualifiedNameId *q = control()->qualifiedNameId(names.data(), names.size(), name->isGlobal()); + _type = control()->namedType(q); + } + + virtual void visit(DestructorNameId *name) + { + Overview oo; + qWarning() << "ignored name:" << oo(name); + } + + virtual void visit(OperatorNameId *name) + { + Overview oo; + qWarning() << "ignored name:" << oo(name); + } + + virtual void visit(ConversionNameId *name) + { + Overview oo; + qWarning() << "ignored name:" << oo(name); + } + + virtual void visit(SelectorNameId *name) + { + Overview oo; + qWarning() << "ignored name:" << oo(name); + } + + private: + ApplySubstitution *q; + FullySpecifiedType _type; + }; + +public: // attributes + LookupContext context; + Symbol *symbol; + GenTemplateInstance::Substitution substitution; + ApplyToType applyToType; + ApplyToName applyToName; +}; + +ApplySubstitution::ApplySubstitution(const LookupContext &context, Symbol *symbol, + const GenTemplateInstance::Substitution &substitution) + : context(context), symbol(symbol), + substitution(substitution), + applyToType(this), applyToName(this) +{ } -FullySpecifiedType GenTemplateInstance::subst(const FullySpecifiedType &ty) +ApplySubstitution::~ApplySubstitution() { - FullySpecifiedType previousType = switchType(ty); - TypeVisitor::accept(ty.type()); - return switchType(previousType); } -FullySpecifiedType GenTemplateInstance::switchType(const FullySpecifiedType &type) +FullySpecifiedType ApplySubstitution::apply(Name *name) { - FullySpecifiedType previousType = _type; - _type = type; - return previousType; + FullySpecifiedType ty = applyToName(name); + return ty; } -// types -void GenTemplateInstance::visit(PointerToMemberType * /*ty*/) +FullySpecifiedType ApplySubstitution::apply(const FullySpecifiedType &type) { - Q_ASSERT(false); + FullySpecifiedType ty = applyToType(type); + return ty; } -void GenTemplateInstance::visit(PointerType *ty) +int ApplySubstitution::findSubstitution(Identifier *id) const { - FullySpecifiedType elementType = subst(ty->elementType()); - _type.setType(_control->pointerType(elementType)); -} + Q_ASSERT(id != 0); -void GenTemplateInstance::visit(ReferenceType *ty) -{ - FullySpecifiedType elementType = subst(ty->elementType()); - _type.setType(_control->referenceType(elementType)); -} + for (int index = 0; index < substitution.size(); ++index) { + QPair<Identifier *, FullySpecifiedType> s = substitution.at(index); -void GenTemplateInstance::visit(ArrayType *ty) -{ - FullySpecifiedType elementType = subst(ty->elementType()); - _type.setType(_control->arrayType(elementType, ty->size())); -} + if (id->isEqualTo(s.first)) + return index; + } -void GenTemplateInstance::visit(NamedType *ty) -{ - Name *name = ty->name(); - _type.setType(subst(name).type()); + return -1; } -void GenTemplateInstance::visit(Function *ty) +FullySpecifiedType ApplySubstitution::applySubstitution(int index) const { - Name *name = ty->name(); - FullySpecifiedType returnType = subst(ty->returnType()); - - Function *fun = _control->newFunction(0, name); - fun->setScope(ty->scope()); - fun->setConst(ty->isConst()); - fun->setVolatile(ty->isVolatile()); - fun->setReturnType(returnType); - for (unsigned i = 0; i < ty->argumentCount(); ++i) { - Symbol *arg = ty->argumentAt(i); - FullySpecifiedType argTy = subst(arg->type()); - Argument *newArg = _control->newArgument(0, arg->name()); - newArg->setType(argTy); - fun->arguments()->enterSymbol(newArg); - } - _type.setType(fun); -} - -void GenTemplateInstance::visit(VoidType *) -{ /* nothing to do*/ } - -void GenTemplateInstance::visit(IntegerType *) -{ /* nothing to do*/ } - -void GenTemplateInstance::visit(FloatType *) -{ /* nothing to do*/ } - -void GenTemplateInstance::visit(Namespace *) -{ Q_ASSERT(false); } + Q_ASSERT(index != -1); + Q_ASSERT(index < substitution.size()); -void GenTemplateInstance::visit(Class *) -{ Q_ASSERT(false); } - -void GenTemplateInstance::visit(Enum *) -{ Q_ASSERT(false); } - -// names -void GenTemplateInstance::visit(NameId *) -{ Q_ASSERT(false); } - -void GenTemplateInstance::visit(TemplateNameId *) -{ Q_ASSERT(false); } - -void GenTemplateInstance::visit(DestructorNameId *) -{ Q_ASSERT(false); } + return substitution.at(index).second; +} -void GenTemplateInstance::visit(OperatorNameId *) -{ Q_ASSERT(false); } +} // end of anonymous namespace -void GenTemplateInstance::visit(ConversionNameId *) -{ Q_ASSERT(false); } +GenTemplateInstance::GenTemplateInstance(const LookupContext &context, const Substitution &substitution) + : _symbol(0), + _context(context), + _substitution(substitution) +{ } -void GenTemplateInstance::visit(QualifiedNameId *) -{ Q_ASSERT(false); } +FullySpecifiedType GenTemplateInstance::operator()(Symbol *symbol) +{ + ApplySubstitution o(_context, symbol, _substitution); + return o.apply(symbol->type()); +} +Control *GenTemplateInstance::control() const +{ return _context.control(); } diff --git a/src/libs/cplusplus/GenTemplateInstance.h b/src/libs/cplusplus/GenTemplateInstance.h index a4845f8bc3d151ce8e6adc5e17a7be7be0b8ae06..a59d1a74717ac50368ac97febca2e5693b97f2f4 100644 --- a/src/libs/cplusplus/GenTemplateInstance.h +++ b/src/libs/cplusplus/GenTemplateInstance.h @@ -1,3 +1,32 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 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 GENTEMPLATEINSTANCE_H #define GENTEMPLATEINSTANCE_H @@ -5,51 +34,28 @@ #include <NameVisitor.h> #include <FullySpecifiedType.h> +#include "LookupContext.h" + #include <QtCore/QList> #include <QtCore/QPair> namespace CPlusPlus { -class CPLUSPLUS_EXPORT GenTemplateInstance: protected TypeVisitor, protected NameVisitor +class CPLUSPLUS_EXPORT GenTemplateInstance { public: - typedef QList< QPair<Name *, FullySpecifiedType> > Substitution; + typedef QList< QPair<Identifier *, FullySpecifiedType> > Substitution; public: - GenTemplateInstance(Control *control, const Substitution &substitution); - - FullySpecifiedType operator()(const FullySpecifiedType &ty); - -protected: - FullySpecifiedType subst(Name *name); - FullySpecifiedType subst(const FullySpecifiedType &ty); - - FullySpecifiedType switchType(const FullySpecifiedType &type); - - virtual void visit(PointerToMemberType * /*ty*/); - virtual void visit(PointerType *ty); - virtual void visit(ReferenceType *ty); - virtual void visit(ArrayType *ty); - virtual void visit(NamedType *ty); - virtual void visit(Function *ty); - virtual void visit(VoidType *); - virtual void visit(IntegerType *); - virtual void visit(FloatType *); - virtual void visit(Namespace *); - virtual void visit(Class *); - virtual void visit(Enum *); - - // names - virtual void visit(NameId *); - virtual void visit(TemplateNameId *); - virtual void visit(DestructorNameId *); - virtual void visit(OperatorNameId *); - virtual void visit(ConversionNameId *); - virtual void visit(QualifiedNameId *); + GenTemplateInstance(const LookupContext &context, const Substitution &substitution); + + FullySpecifiedType operator()(Symbol *symbol); + + Control *control() const; private: - Control *_control; - FullySpecifiedType _type; + Symbol *_symbol; + LookupContext _context; const Substitution _substitution; }; diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index ef8b11ccb1a026d0646352e74abaa2868d63e1da..4d3ed932759f5dee2d490a7c33bd38ce71daaf0a 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -347,8 +347,10 @@ QList<Scope *> LookupContext::buildVisibleScopes() } QList<Scope *> LookupContext::visibleScopes(const QPair<FullySpecifiedType, Symbol *> &result) const +{ return visibleScopes(result.second); } + +QList<Scope *> LookupContext::visibleScopes(Symbol *symbol) const { - Symbol *symbol = result.second; QList<Scope *> scopes; for (Scope *scope = symbol->scope(); scope; scope = scope->enclosingScope()) scopes.append(scope); diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index 5424da869ca4efda055195d5762a6dd68beced9f..e9d84c83aeccd1fe8f7a053134ed2d222cb03c7d 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -98,6 +98,7 @@ public: QList<Scope *> visibleScopes() const { return _visibleScopes; } + QList<Scope *> visibleScopes(Symbol *symbol) const; QList<Scope *> visibleScopes(const QPair<FullySpecifiedType, Symbol *> &result) const; QList<Scope *> expand(const QList<Scope *> &scopes) const; diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index f89c2c9afd5bb0c0c3c6a5f905e51e1f5e384282..2ae4f84da1cb83d09c8e0d99073e189f45765aba 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -566,6 +566,11 @@ ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int a FullySpecifiedType ty = result.first.simplified(); Symbol *lastVisibleSymbol = result.second; + if (Function *funTy = ty->asFunctionType()) { + if (funTy->isAmbiguous()) + ty = funTy->returnType().simplified(); + } + if (accessOp == T_ARROW) { if (lastVisibleSymbol && ty->isClassType() && ! lastVisibleSymbol->isClass()) { // ### remove ! lastVisibleSymbol->isClass() from the condition. @@ -695,7 +700,7 @@ ResolveExpression::resolveMember(Name *memberName, Class *klass, QList<Scope *> scopes; _context.expand(klass->members(), _context.visibleScopes(), &scopes); - QList<Symbol *> candidates = _context.resolve(memberName, scopes); + const QList<Symbol *> candidates = _context.resolve(memberName, scopes); foreach (Symbol *candidate, candidates) { FullySpecifiedType ty = candidate->type(); @@ -710,13 +715,17 @@ ResolveExpression::resolveMember(Name *memberName, Class *klass, for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) { FullySpecifiedType templArgTy = templId->templateArgumentAt(i); - if (i < klass->templateParameterCount()) - subst.append(qMakePair(klass->templateParameterAt(i)->name(), - templArgTy)); + if (i < klass->templateParameterCount()) { + Name *templArgName = klass->templateParameterAt(i)->name(); + if (templArgName && templArgName->identifier()) { + Identifier *templArgId = templArgName->identifier(); + subst.append(qMakePair(templArgId, templArgTy)); + } + } } - GenTemplateInstance inst(control(), subst); - ty = inst(ty); + GenTemplateInstance inst(_context, subst); + ty = inst(candidate); } results.append(Result(ty, candidate)); diff --git a/src/libs/cplusplus/cplusplus-lib.pri b/src/libs/cplusplus/cplusplus-lib.pri index 812dbe0c9a41bbd6f73642fedf25422b67ae1596..611fadf0ac409ec6244da5818ca2d9613c5c22ae 100644 --- a/src/libs/cplusplus/cplusplus-lib.pri +++ b/src/libs/cplusplus/cplusplus-lib.pri @@ -1,4 +1,9 @@ -DEFINES += CPLUSPLUS_BUILD_LIB +contains(CONFIG, dll) { + DEFINES += CPLUSPLUS_BUILD_LIB +} else { + DEFINES += CPLUSPLUS_BUILD_STATIC_LIB +} + INCLUDEPATH += $$PWD include(../../shared/cplusplus/cplusplus.pri) @@ -33,6 +38,7 @@ HEADERS += \ $$PWD/CppBindings.h \ $$PWD/ASTParent.h \ $$PWD/GenTemplateInstance.h \ + $$PWD/FindUsages.h \ $$PWD/CheckUndefinedSymbols.h \ $$PWD/PreprocessorClient.h \ $$PWD/PreprocessorEnvironment.h \ @@ -56,6 +62,7 @@ SOURCES += \ $$PWD/CppBindings.cpp \ $$PWD/ASTParent.cpp \ $$PWD/GenTemplateInstance.cpp \ + $$PWD/FindUsages.cpp \ $$PWD/CheckUndefinedSymbols.cpp \ $$PWD/PreprocessorClient.cpp \ $$PWD/PreprocessorEnvironment.cpp \ diff --git a/src/libs/cplusplus/cplusplus.pro b/src/libs/cplusplus/cplusplus.pro index a6e804439ba0a2a707a6c3e2454cd4d6bc32f430..88c6b18e3d320223f5c2341f6b8fa41d5b4ad569 100644 --- a/src/libs/cplusplus/cplusplus.pro +++ b/src/libs/cplusplus/cplusplus.pro @@ -1,5 +1,5 @@ TEMPLATE = lib - +CONFIG+=dll TARGET = CPlusPlus DEFINES += NDEBUG diff --git a/src/libs/utils/utils.pro b/src/libs/utils/utils.pro index 74939e2f063b917e6cdf1cc72d6a244f07b1659f..88687c63b433d7e928310d1805cf176b4c68d4ea 100644 --- a/src/libs/utils/utils.pro +++ b/src/libs/utils/utils.pro @@ -2,7 +2,7 @@ TEMPLATE = lib TARGET = Utils QT += gui \ network -DEFINES += QTCREATOR_UTILS_LIBRARY +DEFINES += QTCREATOR_UTILS_LIB include(../../qtcreatorlibrary.pri) SOURCES += reloadpromptutils.cpp \ settingsutils.cpp \ diff --git a/src/libs/utils/utils_global.h b/src/libs/utils/utils_global.h index a36b6e728b5a94348002307d32d67e4f14d1b4e4..f158766087e12a40f2d272910dd956cff0430642 100644 --- a/src/libs/utils/utils_global.h +++ b/src/libs/utils/utils_global.h @@ -32,8 +32,10 @@ #include <QtCore/qglobal.h> -#if defined(QTCREATOR_UTILS_LIBRARY) +#if defined(QTCREATOR_UTILS_LIB) # define QTCREATOR_UTILS_EXPORT Q_DECL_EXPORT +#elif defined(QTCREATOR_UTILS_STATIC_LIB) // Abuse single files for manual tests +# define QTCREATOR_UTILS_EXPORT #else # define QTCREATOR_UTILS_EXPORT Q_DECL_IMPORT #endif diff --git a/src/libs/utils/welcomemodetreewidget.cpp b/src/libs/utils/welcomemodetreewidget.cpp index 1fd3b52a432741f42c5b59d69249e474473330cd..b5cd3489515040255055dcedaecdc91b3e2a821e 100644 --- a/src/libs/utils/welcomemodetreewidget.cpp +++ b/src/libs/utils/welcomemodetreewidget.cpp @@ -30,6 +30,7 @@ #include "welcomemodetreewidget.h" #include <QtGui/QLabel> +#include <QtGui/QAction> #include <QtGui/QBoxLayout> #include <QtGui/QHeaderView> @@ -78,7 +79,7 @@ QSize WelcomeModeTreeWidget::sizeHint() const return QSize(QTreeWidget::sizeHint().width(), 30 * topLevelItemCount()); } -QTreeWidgetItem *WelcomeModeTreeWidget::addItem(const QString &label, const QString &data) +QTreeWidgetItem *WelcomeModeTreeWidget::addItem(const QString &label, const QString &data, const QString &toolTip) { QTreeWidgetItem *item = new QTreeWidgetItem(this); item->setIcon(0, m_d->bullet); @@ -94,7 +95,10 @@ QTreeWidgetItem *WelcomeModeTreeWidget::addItem(const QString &label, const QStr wdg->setLayout(lay); setItemWidget(item, 1, wdg); item->setData(0, Qt::UserRole, data); + if (!toolTip.isEmpty()) + wdg->setToolTip(toolTip); return item; + } void WelcomeModeTreeWidget::slotAddNewsItem(const QString &title, const QString &description, const QString &link) @@ -105,7 +109,7 @@ void WelcomeModeTreeWidget::slotAddNewsItem(const QString &title, const QString f.setBold(true); QString elidedTitle = QFontMetrics(f).elidedText(title, Qt::ElideRight, itemWidth); QString data = QString::fromLatin1("<b>%1</b><br />%2").arg(elidedTitle).arg(elidedText); - addTopLevelItem(addItem(data,link)); + addTopLevelItem(addItem(data, link, link)); } void WelcomeModeTreeWidget::slotItemClicked(QTreeWidgetItem *item) diff --git a/src/libs/utils/welcomemodetreewidget.h b/src/libs/utils/welcomemodetreewidget.h index 61ae5b6de8cbe3ae79b0521d22b31e117a60fdbc..2dc4cc2f92830be524433a6e14ab00108e569ad3 100644 --- a/src/libs/utils/welcomemodetreewidget.h +++ b/src/libs/utils/welcomemodetreewidget.h @@ -56,7 +56,7 @@ class QTCREATOR_UTILS_EXPORT WelcomeModeTreeWidget : public QTreeWidget public: WelcomeModeTreeWidget(QWidget *parent = 0); ~WelcomeModeTreeWidget(); - QTreeWidgetItem *addItem(const QString &label, const QString &data); + QTreeWidgetItem *addItem(const QString &label, const QString &data,const QString &toolTip = QString::null); public slots: void slotAddNewsItem(const QString &title, const QString &description, const QString &link); diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 3fc55c3bad1ec0343bca37e7592efb330a0134c0..82927da6e03a564275db5bc2de62392c054cdb78 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -497,11 +497,13 @@ ProjectExplorer::FolderNode *CMakeProject::findOrCreateFolder(CMakeProjectNode * QString relativePath = QDir(QFileInfo(rootNode->path()).path()).relativeFilePath(directory); QStringList parts = relativePath.split("/", QString::SkipEmptyParts); ProjectExplorer::FolderNode *parent = rootNode; + QString path = QFileInfo(rootNode->path()).path(); foreach (const QString &part, parts) { + path += "/" + part; // Find folder in subFolders bool found = false; foreach (ProjectExplorer::FolderNode *folder, parent->subFolderNodes()) { - if (QFileInfo(folder->path()).fileName() == part) { + if (folder->path() == path) { // yeah found something :) parent = folder; found = true; @@ -510,7 +512,8 @@ ProjectExplorer::FolderNode *CMakeProject::findOrCreateFolder(CMakeProjectNode * } if (!found) { // No FolderNode yet, so create it - ProjectExplorer::FolderNode *tmp = new ProjectExplorer::FolderNode(part); + ProjectExplorer::FolderNode *tmp = new ProjectExplorer::FolderNode(path); + tmp->setFolderName(part); rootNode->addFolderNodes(QList<ProjectExplorer::FolderNode *>() << tmp, parent); parent = tmp; } diff --git a/src/plugins/cmakeprojectmanager/makestep.cpp b/src/plugins/cmakeprojectmanager/makestep.cpp index 1d88b4cddac5c9619c2298271031762163e38f5e..3a9b975882e92a0e3734f3604d6e13cda9d2f4b3 100644 --- a/src/plugins/cmakeprojectmanager/makestep.cpp +++ b/src/plugins/cmakeprojectmanager/makestep.cpp @@ -132,9 +132,11 @@ void MakeStep::setBuildTarget(const QString &buildConfiguration, const QString & { QStringList old = value(buildConfiguration, "buildTargets").toStringList(); if (on && !old.contains(target)) - setValue(buildConfiguration, "buildTargets", old << target); + old.append(target); else if(!on && old.contains(target)) - setValue(buildConfiguration, "buildTargets", old.removeOne(target)); + old.removeOne(target); + + setValue(buildConfiguration, "buildTargets", old); } QStringList MakeStep::additionalArguments(const QString &buildConfiguration) const diff --git a/src/plugins/cpptools/cppfindreferences.cpp b/src/plugins/cpptools/cppfindreferences.cpp index 06ae9790602dc07c6bc14437d4b00fc5606c29c7..01f7668d7d50954077716225ff66662f91d8933e 100644 --- a/src/plugins/cpptools/cppfindreferences.cpp +++ b/src/plugins/cpptools/cppfindreferences.cpp @@ -50,11 +50,7 @@ #include <cplusplus/CppDocument.h> #include <cplusplus/CppBindings.h> -#include <cplusplus/ExpressionUnderCursor.h> -#include <cplusplus/ResolveExpression.h> #include <cplusplus/Overview.h> -#include <cplusplus/TypeOfExpression.h> -#include <cplusplus/FastPreprocessor.h> #include <QtCore/QTime> #include <QtCore/QtConcurrentRun> @@ -65,438 +61,6 @@ using namespace CppTools::Internal; using namespace CPlusPlus; -namespace { - -struct Process: protected ASTVisitor -{ -public: - Process(Document::Ptr doc, const Snapshot &snapshot, - QFutureInterface<Utils::FileSearchResult> *future) - : ASTVisitor(doc->control()), - _future(future), - _doc(doc), - _snapshot(snapshot), - _source(_doc->source()), - _sem(doc->control()), - _inSimpleDeclaration(0) - { - _snapshot.insert(_doc); - } - - void setGlobalNamespaceBinding(NamespaceBindingPtr globalNamespaceBinding) - { - _globalNamespaceBinding = globalNamespaceBinding; - } - - QList<int> operator()(Symbol *symbol, Identifier *id, AST *ast) - { - _references.clear(); - _declSymbol = symbol; - _id = id; - _exprDoc = Document::create("<references>"); - accept(ast); - return _references; - } - -protected: - using ASTVisitor::visit; - - QString matchingLine(const Token &tk) const - { - const char *beg = _source.constData(); - const char *cp = beg + tk.offset; - for (; cp != beg - 1; --cp) { - if (*cp == '\n') - break; - } - - ++cp; - - const char *lineEnd = cp + 1; - for (; *lineEnd; ++lineEnd) { - if (*lineEnd == '\n') - break; - } - - const QString matchingLine = QString::fromUtf8(cp, lineEnd - cp); - return matchingLine; - - } - - void reportResult(unsigned tokenIndex, const QList<Symbol *> &candidates) - { - const bool isStrongResult = checkCandidates(candidates); - - if (isStrongResult) - reportResult(tokenIndex); - } - - void reportResult(unsigned tokenIndex) - { - const Token &tk = tokenAt(tokenIndex); - const QString lineText = matchingLine(tk); - - unsigned line, col; - getTokenStartPosition(tokenIndex, &line, &col); - - if (col) - --col; // adjust the column position. - - const int len = tk.f.length; - - if (_future) - _future->reportResult(Utils::FileSearchResult(QDir::toNativeSeparators(_doc->fileName()), - line, lineText, col, len)); - - _references.append(tokenIndex); - } - - bool checkCandidates(const QList<Symbol *> &candidates) const - { - if (Symbol *canonicalSymbol = LookupContext::canonicalSymbol(candidates, _globalNamespaceBinding.data())) { - -#if 0 - qDebug() << "*** canonical symbol:" << canonicalSymbol->fileName() - << canonicalSymbol->line() << canonicalSymbol->column() - << "candidates:" << candidates.size(); -#endif - - return isDeclSymbol(canonicalSymbol); - } - - return false; - } - - bool checkScope(Symbol *symbol, Symbol *otherSymbol) const - { - if (! (symbol && otherSymbol)) - return false; - - else if (symbol->scope() == otherSymbol->scope()) - return true; - - else if (symbol->name() && otherSymbol->name()) { - - if (! symbol->name()->isEqualTo(otherSymbol->name())) - return false; - - } else if (symbol->name() != otherSymbol->name()) { - return false; - } - - return checkScope(symbol->enclosingSymbol(), otherSymbol->enclosingSymbol()); - } - - bool isDeclSymbol(Symbol *symbol) const - { - if (! symbol) { - return false; - - } else if (symbol == _declSymbol) { - return true; - - } else if (symbol->line() == _declSymbol->line() && symbol->column() == _declSymbol->column()) { - if (! qstrcmp(symbol->fileName(), _declSymbol->fileName())) - return true; - - } else if (symbol->isForwardClassDeclaration() && (_declSymbol->isClass() || - _declSymbol->isForwardClassDeclaration())) { - return checkScope(symbol, _declSymbol); - - } else if (_declSymbol->isForwardClassDeclaration() && (symbol->isClass() || - symbol->isForwardClassDeclaration())) { - return checkScope(symbol, _declSymbol); - } - - return false; - } - - LookupContext _previousContext; - - LookupContext currentContext(AST *ast) - { - unsigned line, column; - getTokenStartPosition(ast->firstToken(), &line, &column); - Symbol *lastVisibleSymbol = _doc->findSymbolAt(line, column); - - if (lastVisibleSymbol && lastVisibleSymbol == _previousContext.symbol()) - return _previousContext; - - LookupContext ctx(lastVisibleSymbol, _exprDoc, _doc, _snapshot); - _previousContext = ctx; - return ctx; - } - - void ensureNameIsValid(NameAST *ast) - { - if (ast && ! ast->name) - ast->name = _sem.check(ast, /*scope = */ 0); - } - - virtual bool visit(MemInitializerAST *ast) - { - if (ast->name && ast->name->asSimpleName() != 0) { - ensureNameIsValid(ast->name); - - SimpleNameAST *simple = ast->name->asSimpleName(); - if (identifier(simple->identifier_token) == _id) { - LookupContext context = currentContext(ast); - const QList<Symbol *> candidates = context.resolve(simple->name); - reportResult(simple->identifier_token, candidates); - } - } - accept(ast->expression); - return false; - } - - virtual bool visit(PostfixExpressionAST *ast) - { - _postfixExpressionStack.append(ast); - return true; - } - - virtual void endVisit(PostfixExpressionAST *) - { - _postfixExpressionStack.removeLast(); - } - - virtual bool visit(MemberAccessAST *ast) - { - if (ast->member_name) { - if (SimpleNameAST *simple = ast->member_name->asSimpleName()) { - if (identifier(simple->identifier_token) == _id) { - Q_ASSERT(! _postfixExpressionStack.isEmpty()); - - checkExpression(_postfixExpressionStack.last()->firstToken(), - simple->identifier_token); - - return false; - } - } - } - - return true; - } - - void checkExpression(unsigned startToken, unsigned endToken) - { - const unsigned begin = tokenAt(startToken).begin(); - const unsigned end = tokenAt(endToken).end(); - - const QString expression = _source.mid(begin, end - begin); - // qDebug() << "*** check expression:" << expression; - - TypeOfExpression typeofExpression; - typeofExpression.setSnapshot(_snapshot); - - unsigned line, column; - getTokenStartPosition(startToken, &line, &column); - Symbol *lastVisibleSymbol = _doc->findSymbolAt(line, column); - - const QList<TypeOfExpression::Result> results = - typeofExpression(expression, _doc, lastVisibleSymbol, - TypeOfExpression::Preprocess); - - QList<Symbol *> candidates; - - foreach (TypeOfExpression::Result r, results) { - FullySpecifiedType ty = r.first; - Symbol *lastVisibleSymbol = r.second; - - candidates.append(lastVisibleSymbol); - } - - reportResult(endToken, candidates); - } - - virtual bool visit(QualifiedNameAST *ast) - { - for (NestedNameSpecifierAST *nested_name_specifier = ast->nested_name_specifier; - nested_name_specifier; nested_name_specifier = nested_name_specifier->next) { - - if (NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name) { - SimpleNameAST *simple_name = class_or_namespace_name->asSimpleName(); - - TemplateIdAST *template_id = 0; - if (! simple_name) { - template_id = class_or_namespace_name->asTemplateId(); - - if (template_id) { - for (TemplateArgumentListAST *template_arguments = template_id->template_arguments; - template_arguments; template_arguments = template_arguments->next) { - accept(template_arguments->template_argument); - } - } - } - - if (simple_name || template_id) { - const unsigned identifier_token = simple_name - ? simple_name->identifier_token - : template_id->identifier_token; - - if (identifier(identifier_token) == _id) - checkExpression(ast->firstToken(), identifier_token); - } - } - } - - if (NameAST *unqualified_name = ast->unqualified_name) { - unsigned identifier_token = 0; - - if (SimpleNameAST *simple_name = unqualified_name->asSimpleName()) - identifier_token = simple_name->identifier_token; - - else if (DestructorNameAST *dtor_name = unqualified_name->asDestructorName()) - identifier_token = dtor_name->identifier_token; - - TemplateIdAST *template_id = 0; - if (! identifier_token) { - template_id = unqualified_name->asTemplateId(); - - if (template_id) { - identifier_token = template_id->identifier_token; - - for (TemplateArgumentListAST *template_arguments = template_id->template_arguments; - template_arguments; template_arguments = template_arguments->next) { - accept(template_arguments->template_argument); - } - } - } - - if (identifier_token && identifier(identifier_token) == _id) - checkExpression(ast->firstToken(), identifier_token); - } - - return false; - } - - virtual bool visit(EnumeratorAST *ast) - { - Identifier *id = identifier(ast->identifier_token); - if (id == _id) { - LookupContext context = currentContext(ast); - const QList<Symbol *> candidates = context.resolve(control()->nameId(id)); - reportResult(ast->identifier_token, candidates); - } - - accept(ast->expression); - - return false; - } - - virtual bool visit(SimpleNameAST *ast) - { - Identifier *id = identifier(ast->identifier_token); - if (id == _id) { - LookupContext context = currentContext(ast); - const QList<Symbol *> candidates = context.resolve(ast->name); - reportResult(ast->identifier_token, candidates); - } - - return false; - } - - virtual bool visit(DestructorNameAST *ast) - { - Identifier *id = identifier(ast->identifier_token); - if (id == _id) { - LookupContext context = currentContext(ast); - const QList<Symbol *> candidates = context.resolve(ast->name); - reportResult(ast->identifier_token, candidates); - } - - return false; - } - - virtual bool visit(TemplateIdAST *ast) - { - if (_id == identifier(ast->identifier_token)) { - LookupContext context = currentContext(ast); - const QList<Symbol *> candidates = context.resolve(ast->name); - reportResult(ast->identifier_token, candidates); - } - - for (TemplateArgumentListAST *template_arguments = ast->template_arguments; - template_arguments; template_arguments = template_arguments->next) { - accept(template_arguments->template_argument); - } - - return false; - } - - virtual bool visit(ParameterDeclarationAST *ast) - { - for (SpecifierAST *spec = ast->type_specifier; spec; spec = spec->next) - accept(spec); - - if (DeclaratorAST *declarator = ast->declarator) { - for (SpecifierAST *attr = declarator->attributes; attr; attr = attr->next) - accept(attr); - - for (PtrOperatorAST *ptr_op = declarator->ptr_operators; ptr_op; ptr_op = ptr_op->next) - accept(ptr_op); - - if (! _inSimpleDeclaration) // visit the core declarator only if we are not in simple-declaration. - accept(declarator->core_declarator); - - for (PostfixDeclaratorAST *fx_op = declarator->postfix_declarators; fx_op; fx_op = fx_op->next) - accept(fx_op); - - for (SpecifierAST *spec = declarator->post_attributes; spec; spec = spec->next) - accept(spec); - - accept(declarator->initializer); - } - - accept(ast->expression); - return false; - } - - virtual bool visit(ExpressionOrDeclarationStatementAST *ast) - { - accept(ast->declaration); - return false; - } - - virtual bool visit(FunctionDeclaratorAST *ast) - { - accept(ast->parameters); - - for (SpecifierAST *spec = ast->cv_qualifier_seq; spec; spec = spec->next) - accept(spec); - - accept(ast->exception_specification); - - return false; - } - - virtual bool visit(SimpleDeclarationAST *) - { - ++_inSimpleDeclaration; - return true; - } - - virtual void endVisit(SimpleDeclarationAST *) - { --_inSimpleDeclaration; } - -private: - QFutureInterface<Utils::FileSearchResult> *_future; - Identifier *_id; // ### remove me - Symbol *_declSymbol; - Document::Ptr _doc; - Snapshot _snapshot; - QByteArray _source; - Document::Ptr _exprDoc; - Semantic _sem; - NamespaceBindingPtr _globalNamespaceBinding; - QList<PostfixExpressionAST *> _postfixExpressionStack; - QList<QualifiedNameAST *> _qualifiedNameStack; - QList<int> _references; - int _inSimpleDeclaration; -}; - -} // end of anonymous namespace - CppFindReferences::CppFindReferences(CppTools::CppModelManagerInterface *modelManager) : _modelManager(modelManager), _resultWindow(ExtensionSystem::PluginManager::instance()->getObject<Find::SearchResultWindow>()) @@ -526,14 +90,14 @@ QList<int> CppFindReferences::references(Symbol *symbol, TranslationUnit *translationUnit = doc->translationUnit(); Q_ASSERT(translationUnit != 0); - Process process(doc, snapshot, /*future = */ 0); + FindUsages process(doc, snapshot, /*future = */ 0); process.setGlobalNamespaceBinding(bind(doc, snapshot)); references = process(symbol, id, translationUnit->ast()); return references; } -static void find_helper(QFutureInterface<Utils::FileSearchResult> &future, +static void find_helper(QFutureInterface<Usage> &future, const QMap<QString, QString> wl, Snapshot snapshot, Symbol *symbol) @@ -562,6 +126,8 @@ static void find_helper(QFutureInterface<Utils::FileSearchResult> &future, files += snapshot.dependsOn(sourceFile); } + files.removeDuplicates(); + //qDebug() << "done in:" << tm.elapsed() << "number of files to parse:" << files.size(); future.setProgressRange(0, files.size()); @@ -613,7 +179,7 @@ static void find_helper(QFutureInterface<Utils::FileSearchResult> &future, tm.start(); - Process process(doc, snapshot, &future); + FindUsages process(doc, snapshot, &future); process.setGlobalNamespaceBinding(bind(doc, snapshot)); TranslationUnit *unit = doc->translationUnit(); @@ -666,7 +232,7 @@ void CppFindReferences::findAll_helper(Symbol *symbol) Core::ProgressManager *progressManager = Core::ICore::instance()->progressManager(); - QFuture<Utils::FileSearchResult> result = QtConcurrent::run(&find_helper, wl, snapshot, symbol); + QFuture<Usage> result = QtConcurrent::run(&find_helper, wl, snapshot, symbol); m_watcher.setFuture(result); Core::FutureProgress *progress = progressManager->addTask(result, tr("Searching..."), @@ -759,12 +325,12 @@ void CppFindReferences::onReplaceButtonClicked(const QString &text, void CppFindReferences::displayResult(int index) { - Utils::FileSearchResult result = m_watcher.future().resultAt(index); - _resultWindow->addResult(result.fileName, - result.lineNumber, - result.matchingLine, - result.matchStart, - result.matchLength); + Usage result = m_watcher.future().resultAt(index); + _resultWindow->addResult(result.path, + result.line, + result.lineText, + result.col, + result.len); } void CppFindReferences::searchFinished() diff --git a/src/plugins/cpptools/cppfindreferences.h b/src/plugins/cpptools/cppfindreferences.h index cbddf8fb5c3458d448ca13a908173be8d8e11338..61ba876546fd9d3320cb9da2ad3d327f51dd7d82 100644 --- a/src/plugins/cpptools/cppfindreferences.h +++ b/src/plugins/cpptools/cppfindreferences.h @@ -36,6 +36,7 @@ #include <QtCore/QFutureWatcher> #include <utils/filesearch.h> #include <cplusplus/CppDocument.h> +#include <cplusplus/FindUsages.h> namespace Find { class SearchResultWindow; @@ -78,7 +79,7 @@ private: private: QPointer<CppModelManagerInterface> _modelManager; Find::SearchResultWindow *_resultWindow; - QFutureWatcher<Utils::FileSearchResult> m_watcher; + QFutureWatcher<CPlusPlus::Usage> m_watcher; }; } // end of namespace Internal diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 48d2f418a970274448d94d6ac159bebbd366c09e..468203d9929dcfa0feab4ae752d70d3b401f7190 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -180,7 +180,7 @@ using namespace Debugger::Internal; static const QString tooltipIName = "tooltip"; -static const char *stateName(int s) +const char *DebuggerManager::stateName(int s) { #define SN(x) case x: return #x; switch (s) { @@ -1470,20 +1470,19 @@ void DebuggerManager::showQtDumperLibraryWarning(const QString &details) QMessageBox dialog(mainWindow()); QPushButton *qtPref = dialog.addButton(tr("Open Qt preferences"), QMessageBox::ActionRole); - QPushButton *helperOff = dialog.addButton(tr("Turn helper usage off"), + QPushButton *helperOff = dialog.addButton(tr("Turn off helper usage"), QMessageBox::ActionRole); QPushButton *justContinue = dialog.addButton(tr("Continue anyway"), QMessageBox::AcceptRole); dialog.setDefaultButton(justContinue); dialog.setWindowTitle(tr("Debugging helper missing")); - dialog.setText(tr("The debugger did not find the debugging helper library.")); + dialog.setText(tr("The debugger could not load the debugging helper library.")); dialog.setInformativeText(tr( "The debugging helper is used to nicely format the values of some Qt " "and Standard Library data types. " - "It must be compiled for each Qt version which " - "you can do in the Qt preferences page by selecting " - "a Qt installation and clicking on 'Rebuild' for the debugging " - "helper.")); + "It must be compiled for each used Qt version separately. " + "This can be done in the Qt preferences page by selecting a Qt installation " + "and clicking on 'Rebuild' in the 'Debugging Helper' row.")); if (!details.isEmpty()) dialog.setDetailedText(details); dialog.exec(); @@ -1753,7 +1752,7 @@ void DebuggerManager::ensureLogVisible() QDebug operator<<(QDebug d, DebuggerState state) { - return d << stateName(state) << '(' << int(state) << ')'; + return d << DebuggerManager::stateName(state) << '(' << int(state) << ')'; } ////////////////////////////////////////////////////////////////////// diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index ff40707d7d0609c76b9aa6b67b88db5ec9b4d298..d78c00bef50604adab1130c5957d1821d6b12dbb 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -244,6 +244,8 @@ public slots: void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever void clearCppCodeModelSnapshot(); + static const char *stateName(int s); + public slots: // FIXME void showDebuggerOutput(const QString &msg) { showDebuggerOutput(LogDebug, msg); } diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 9c8cbdcf725b90956e53dac72a9258053151beff..6fc2b41e0e82fe5c73bd5a81ffc1c667d0207509 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -47,6 +47,7 @@ #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/findplaceholder.h> #include <coreplugin/icore.h> +#include <coreplugin/icorelistener.h> #include <coreplugin/messagemanager.h> #include <coreplugin/minisplitter.h> #include <coreplugin/modemanager.h> @@ -204,6 +205,61 @@ DebugMode::~DebugMode() EditorManager::instance()->setParent(0); } +/////////////////////////////////////////////////////////////////////// +// +// DebuggerListener: Close the debugging session if running. +// +/////////////////////////////////////////////////////////////////////// + +class DebuggerListener : public Core::ICoreListener { + Q_OBJECT +public: + explicit DebuggerListener(QObject *parent = 0); + virtual bool coreAboutToClose(); +}; + +DebuggerListener::DebuggerListener(QObject *parent) : + Core::ICoreListener(parent) +{ +} + +bool DebuggerListener::coreAboutToClose() +{ + DebuggerManager *mgr = DebuggerManager::instance(); + if (!mgr) + return true; + // Ask to terminate the session. + const QString title = tr("Close Debugging Session"); + bool cleanTermination = false; + switch (mgr->state()) { + case DebuggerNotReady: + return true; + case AdapterStarted: // Most importantly, terminating a running + case AdapterStartFailed: // debuggee can cause problems. + case InferiorUnrunnable: + case InferiorStartFailed: + case InferiorStopped: + case InferiorShutDown: + cleanTermination = true; + break; + default: + break; + } + const QString question = cleanTermination ? + tr("A debugging session is still in progress. Would you like to terminate it?") : + tr("A debugging session is still in progress. Terminating the session in the current" + " state (%1) can leave the target in an inconsistent state." + " Would you like to terminate it?") + .arg(QLatin1String(DebuggerManager::stateName(mgr->state()))); + QMessageBox::StandardButton answer = QMessageBox::question(0, title, question, + QMessageBox::Yes|QMessageBox::No, QMessageBox::No); + if (answer == QMessageBox::No) + return false; + mgr->exitDebugger(); + QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); + return true; +} + } // namespace Internal } // namespace Debugger @@ -755,7 +811,7 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess addAutoReleasedObject(new DebuggingHelperOptionPage); foreach (Core::IOptionsPage* op, engineOptionPages) addAutoReleasedObject(op); - + addAutoReleasedObject(new DebuggerListener); m_locationMark = 0; diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index a0ac59ca7339aa1cfd8a213029bec58d0371a6ed..9df41bc62776633dcd97033e56cefe61a6cac302 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -101,6 +101,7 @@ namespace Internal { #else # define PENDING_DEBUG(s) #endif +#define PENDING_DEBUGX(s) qDebug() << s #define CB(callback) &GdbEngine::callback, STRINGIFY(callback) @@ -225,7 +226,7 @@ QMainWindow *GdbEngine::mainWindow() const GdbEngine::~GdbEngine() { // prevent sending error messages afterwards - disconnect(&m_gdbProc); + disconnect(&m_gdbProc, 0, this, 0); delete m_gdbAdapter; m_gdbAdapter = 0; } @@ -692,10 +693,10 @@ void GdbEngine::postCommandHelper(const GdbCommand &cmd) if (cmd.flags & RebuildModel) { ++m_pendingRequests; - PENDING_DEBUG(" CALLBACK" << cmd.callbackName + PENDING_DEBUG(" COMMAND" << cmd.callbackName << "INCREMENTS PENDING TO:" << m_pendingRequests << cmd.command); } else { - PENDING_DEBUG(" UNKNOWN CALLBACK" << cmd.callbackName + PENDING_DEBUG(" UNKNOWN COMMAND" << cmd.callbackName << "LEAVES PENDING AT:" << m_pendingRequests << cmd.command); } @@ -816,14 +817,14 @@ void GdbEngine::handleResultRecord(GdbResponse *response) if (cmd.flags & RebuildModel) { --m_pendingRequests; - PENDING_DEBUG(" TYPE " << cmd.callbackName << " DECREMENTS PENDING TO: " + PENDING_DEBUG(" RESULT " << cmd.callbackName << " DECREMENTS PENDING TO: " << m_pendingRequests << cmd.command); if (m_pendingRequests <= 0) { PENDING_DEBUG("\n\n .... AND TRIGGERS MODEL UPDATE\n"); rebuildModel(); } } else { - PENDING_DEBUG(" UNKNOWN TYPE " << cmd.callbackName << " LEAVES PENDING AT: " + PENDING_DEBUG(" UNKNOWN RESULT " << cmd.callbackName << " LEAVES PENDING AT: " << m_pendingRequests << cmd.command); } @@ -1132,6 +1133,8 @@ void GdbEngine::handleStopResponse(const GdbMi &data) || name != CROSS_STOP_SIGNAL)) initHelpers = false; } + if (isSynchroneous()) + initHelpers = false; if (initHelpers) { tryLoadDebuggingHelpers(); QVariant var = QVariant::fromValue<GdbMi>(data); @@ -2966,6 +2969,22 @@ void GdbEngine::updateWatchData(const WatchData &data) #else if (data.iname.endsWith(_("."))) return; + + // Avoid endless loops created by faulty dumpers. + QString processedName = QString(_("%1-%2").arg(1).arg(data.iname)); + //qDebug() << "PROCESSED NAMES: " << processedName << m_processedNames; + if (m_processedNames.contains(processedName)) { + WatchData data1 = data; + gdbInputAvailable(LogStatus, + _("<Breaking endless loop for %1>").arg(data1.iname)); + data1.setAllUnneeded(); + data1.setValue(_("<unavailable>")); + data1.setHasChildren(false); + insertData(data1); + return; + } + m_processedNames.insert(processedName); + updateLocals(); #endif } else { @@ -3004,7 +3023,8 @@ void GdbEngine::rebuildModel() { static int count = 0; ++count; - m_processedNames.clear(); + if (!isSynchroneous()) + m_processedNames.clear(); PENDING_DEBUG("REBUILDING MODEL" << count); gdbInputAvailable(LogStatus, _("<Rebuild Watchmodel %1>").arg(count)); showStatusMessage(tr("Finished retrieving data."), 400); @@ -3373,27 +3393,28 @@ void GdbEngine::handleDebuggingHelperValue3(const GdbResponse &response) void GdbEngine::updateLocals(const QVariant &cookie) { m_pendingRequests = 0; - m_processedNames.clear(); - - PENDING_DEBUG("\nRESET PENDING"); - //m_toolTipCache.clear(); - m_toolTipExpression.clear(); - manager()->watchHandler()->beginCycle(); - - // Asynchronous load of injected library, initialize in first stop - if (m_dumperInjectionLoad && m_debuggingHelperState == DebuggingHelperLoadTried - && m_dumperHelper.typeCount() == 0 - && inferiorPid() > 0) - tryQueryDebuggingHelpers(); - if (isSynchroneous()) { + manager()->watchHandler()->beginCycle(); + m_toolTipExpression.clear(); QStringList expanded = m_manager->watchHandler()->expandedINames().toList(); postCommand(_("bb %1 %2") .arg(int(theDebuggerBoolSetting(UseDebuggingHelpers))) .arg(expanded.join(_(","))), - CB(handleStackFrame1)); - postCommand(_("p 1"), CB(handleStackFrame2)); + CB(handleStackFrame)); } else { + m_processedNames.clear(); + + PENDING_DEBUG("\nRESET PENDING"); + //m_toolTipCache.clear(); + m_toolTipExpression.clear(); + manager()->watchHandler()->beginCycle(); + + // Asynchronous load of injected library, initialize in first stop + if (m_dumperInjectionLoad && m_debuggingHelperState == DebuggingHelperLoadTried + && m_dumperHelper.typeCount() == 0 + && inferiorPid() > 0) + tryQueryDebuggingHelpers(); + QString level = QString::number(currentFrame()); // '2' is 'list with type and value' QString cmd = _("-stack-list-arguments 2 ") + level + _c(' ') + level; @@ -3404,27 +3425,13 @@ void GdbEngine::updateLocals(const QVariant &cookie) } } -void GdbEngine::handleStackFrame1(const GdbResponse &response) -{ - if (response.resultClass == GdbResultDone) { - QByteArray out = response.data.findChild("consolestreamoutput").data(); - while (out.endsWith(' ') || out.endsWith('\n')) - out.chop(1); - //qDebug() << "FIRST CHUNK: " << out; - m_firstChunk = out; - } else { - QTC_ASSERT(false, qDebug() << response.toString()); - } -} - -void GdbEngine::handleStackFrame2(const GdbResponse &response) +void GdbEngine::handleStackFrame(const GdbResponse &response) { if (response.resultClass == GdbResultDone) { QByteArray out = response.data.findChild("consolestreamoutput").data(); while (out.endsWith(' ') || out.endsWith('\n')) out.chop(1); //qDebug() << "SECOND CHUNK: " << out; - out = m_firstChunk + out; int pos = out.indexOf("locals="); if (pos != 0) { qDebug() << "DISCARDING JUNK AT BEGIN OF RESPONSE: " @@ -3450,7 +3457,13 @@ void GdbEngine::handleStackFrame2(const GdbResponse &response) // FIXME: //manager()->watchHandler()->updateWatchers(); - rebuildModel(); + PENDING_DEBUG("AFTER handleStackFrame()"); + // FIXME: This should only be used when updateLocals() was + // triggered by expanding an item in the view. + if (m_pendingRequests <= 0) { + PENDING_DEBUG("\n\n .... AND TRIGGERS MODEL UPDATE\n"); + rebuildModel(); + } } else { QTC_ASSERT(false, /**/); } @@ -3799,7 +3812,7 @@ void GdbEngine::tryLoadDebuggingHelpers() const QFileInfo fi(lib); if (!fi.exists()) { const QString loc = locations.join(QLatin1String(", ")); - const QString msg = tr("The dumper library was not found at %1.").arg(loc); + const QString msg = tr("The debugging helper library was not found at %1.").arg(loc); debugMessage(msg); manager()->showQtDumperLibraryWarning(msg); return; @@ -3815,10 +3828,10 @@ void GdbEngine::tryLoadDebuggingHelpers() SharedLibraryInjector injector(inferiorPid()); QString errorMessage; if (injector.remoteInject(dlopenLib, false, &errorMessage)) { - debugMessage(tr("Dumper injection loading triggered (%1)..."). + debugMessage(_("Dumper injection loading triggered (%1)..."). arg(dlopenLib)); } else { - debugMessage(tr("Dumper loading (%1) failed: %2"). + debugMessage(_("Dumper loading (%1) failed: %2"). arg(dlopenLib, errorMessage)); debugMessage(errorMessage); manager()->showQtDumperLibraryWarning(errorMessage); @@ -3826,7 +3839,7 @@ void GdbEngine::tryLoadDebuggingHelpers() return; } } else { - debugMessage(tr("Loading dumpers via debugger call (%1)..."). + debugMessage(_("Loading dumpers via debugger call (%1)..."). arg(dlopenLib)); postCommand(_("sharedlibrary .*")); // for LoadLibraryA //postCommand(_("handle SIGSEGV pass stop print")); diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 786ac7696a66937d82c9cf78a76e28f8d847c69b..9e23fee2b2ec67c93274d4a6b70aceab4a4ccc0f 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -370,14 +370,12 @@ private: ////////// View & Data Stuff ////////// void handleStackListFrames(const GdbResponse &response); void handleStackSelectThread(const GdbResponse &response); void handleStackListThreads(const GdbResponse &response); - void handleStackFrame1(const GdbResponse &response); - void handleStackFrame2(const GdbResponse &response); + void handleStackFrame(const GdbResponse &response); Q_SLOT void reloadStack(bool forceGotoLocation); Q_SLOT void reloadFullStack(); int currentFrame() const; QList<GdbMi> m_currentFunctionArgs; - QByteArray m_firstChunk; QString m_currentFrame; // diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 6b774591764af421b61abff2fa1e2f0017a9fe6b..ba7c24ff04f55a8af86aae740acd668dd081a1a1 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -792,7 +792,7 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro if (role == ExpandedRole) { if (value.toBool()) { // Should already have been triggered by fetchMore() - QTC_ASSERT(m_handler->m_expandedINames.contains(data.iname), /**/); + //QTC_ASSERT(m_handler->m_expandedINames.contains(data.iname), /**/); m_handler->m_expandedINames.insert(data.iname); } else { m_handler->m_expandedINames.remove(data.iname); @@ -1095,7 +1095,6 @@ void WatchHandler::beginCycle() void WatchHandler::endCycle() { - //qDebug() << "END CYCLE"; m_locals->endCycle(); m_watchers->endCycle(); m_tooltips->endCycle(); diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp index 3e18cd43f7d3cb1d78a49a992382062fb0c16210..1e1137694fdc9d95578a29e2426436263d97a06c 100644 --- a/src/plugins/debugger/watchutils.cpp +++ b/src/plugins/debugger/watchutils.cpp @@ -755,7 +755,7 @@ void QtDumperHelper::clear() QString QtDumperHelper::msgDumperOutdated(double requiredVersion, double currentVersion) { return QCoreApplication::translate("QtDumperHelper", - "Found a too-old version of the debugging helper library (%1); version %2 is required."). + "Found an outdated version of the debugging helper library (%1); version %2 is required."). arg(currentVersion).arg(requiredVersion); } diff --git a/src/plugins/genericprojectmanager/genericmakestep.cpp b/src/plugins/genericprojectmanager/genericmakestep.cpp index 0ce416f2f5a71e5cdbea0fe51454616b18c50080..57e648d455e4c5fa1440526a7c91d9fd2eb39b3c 100644 --- a/src/plugins/genericprojectmanager/genericmakestep.cpp +++ b/src/plugins/genericprojectmanager/genericmakestep.cpp @@ -142,9 +142,10 @@ void GenericMakeStep::setBuildTarget(const QString &buildConfiguration, const QS { QStringList old = value(buildConfiguration, "buildTargets").toStringList(); if (on && !old.contains(target)) - setValue(buildConfiguration, "buildTargets", old << target); + old << target; else if(!on && old.contains(target)) - setValue(buildConfiguration, "buildTargets", old.removeOne(target)); + old.removeOne(target); + setValue(buildConfiguration, "buildTargets", old); } // diff --git a/src/plugins/projectexplorer/projectwelcomepagewidget.cpp b/src/plugins/projectexplorer/projectwelcomepagewidget.cpp index df576678443a88cbe6a98a4778a8d11b673178c5..4df5f9c9a57c9eb0b1fe4f65b46d248ee725c799 100644 --- a/src/plugins/projectexplorer/projectwelcomepagewidget.cpp +++ b/src/plugins/projectexplorer/projectwelcomepagewidget.cpp @@ -119,9 +119,8 @@ void ProjectWelcomePageWidget::updateWelcomePage(const WelcomePageData &welcomeP typedef QPair<QString, QString> QStringPair; if (welcomePageData.projectList.count() > 0) { foreach (const QStringPair &it, welcomePageData.projectList) { - QTreeWidgetItem *item = ui->projTreeWidget->addItem(it.second, it.first); const QFileInfo fi(it.first); - item->setToolTip(1, QDir::toNativeSeparators(fi.absolutePath())); + QTreeWidgetItem *item = ui->projTreeWidget->addItem(it.second, it.first, fi.absolutePath()); } } else { ui->projTreeWidget->hide(); diff --git a/src/plugins/qmleditor/parser/qmljsastvisitor.cpp b/src/plugins/qmleditor/parser/qmljsastvisitor.cpp index 642bcee26b9818a524f6c1067c65163e047f7e04..d3a1d5306824446887c6601aefc70dd660f37b5a 100644 --- a/src/plugins/qmleditor/parser/qmljsastvisitor.cpp +++ b/src/plugins/qmleditor/parser/qmljsastvisitor.cpp @@ -41,7 +41,7 @@ #include "qmljsastvisitor_p.h" -QT_BEGIN_NAMESPACE +QT_QML_BEGIN_NAMESPACE namespace QmlJS { namespace AST { @@ -55,4 +55,4 @@ Visitor::~Visitor() } } // namespace QmlJS::AST -QT_END_NAMESPACE +QT_QML_END_NAMESPACE diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp index 46ebf4f0443c8d4ed549304377b8ead268f2eaae..a80c4200c98ad52c63353062983a2801fb562013 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp @@ -42,6 +42,7 @@ #include <utils/pathchooser.h> #include <QtCore/QTimer> +#include <QtCore/QDir> #include <QtGui/QRadioButton> #include <QtGui/QLabel> #include <QtGui/QLineEdit> @@ -67,12 +68,13 @@ S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget( m_detailsWidget(new Utils::DetailsWidget), m_serialPortsCombo(new QComboBox), m_nameLineEdit(new QLineEdit(m_runConfiguration->name())), - m_sisxFileLabel(new QLabel(m_runConfiguration->basePackageFilePath() + QLatin1String(".sisx"))), + m_sisxFileLabel(new QLabel), m_deviceInfoButton(new QToolButton), m_deviceInfoDescriptionLabel(new QLabel(tr("Device:"))), m_deviceInfoLabel(new QLabel), m_infoTimeOutTimer(0) { + updateTargetInformation(); QVBoxLayout *mainBoxLayout = new QVBoxLayout(); mainBoxLayout->setMargin(0); setLayout(mainBoxLayout); @@ -100,7 +102,7 @@ S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget( connect(m_serialPortsCombo, SIGNAL(activated(int)), this, SLOT(setSerialPort(int))); QHBoxLayout *serialPortHBoxLayout = new QHBoxLayout; serialPortHBoxLayout->addWidget(m_serialPortsCombo); - serialPortHBoxLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored)); + serialPortHBoxLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); formLayout->addRow(tr("Device on Serial Port:"), serialPortHBoxLayout); @@ -218,7 +220,8 @@ void S60DeviceRunConfigurationWidget::nameEdited(const QString &text) void S60DeviceRunConfigurationWidget::updateTargetInformation() { - m_sisxFileLabel->setText(m_runConfiguration->basePackageFilePath() + QLatin1String(".sisx")); + m_sisxFileLabel->setText(QDir::toNativeSeparators(m_runConfiguration->basePackageFilePath() + + QLatin1String(".sisx"))); } void S60DeviceRunConfigurationWidget::setSerialPort(int index) diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp index a9aa6dceb58d548eac57c3e8cf7df448dcea1411..a9bcc354e0f5c7b9606912b573c068bf1f8d76b4 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devices.cpp @@ -140,6 +140,8 @@ bool S60Devices::readWin() device.toolsRoot = xml.readElementText(); } } + if (device.toolsRoot.isEmpty()) + device.toolsRoot = device.epocRoot; m_devices.append(device); } } @@ -212,6 +214,16 @@ S60Devices::Device S60Devices::deviceForId(const QString &id) const return Device(); } +S60Devices::Device S60Devices::deviceForEpocRoot(const QString &root) const +{ + foreach (const S60Devices::Device &i, m_devices) { + if (i.epocRoot == root) { + return i; + } + } + return Device(); +} + QString S60Devices::cleanedRootPath(const QString &deviceRoot) { QString path = deviceRoot; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devices.h b/src/plugins/qt4projectmanager/qt-s60/s60devices.h index 839fd32967a8896ec5714ba1e18f81e8d900ff41..01173d979af3e7ce131b14002b618642fc4f0e56 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devices.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devices.h @@ -63,6 +63,7 @@ public: QList<Device> devices() const; bool detectQtForDevices(); Device deviceForId(const QString &id) const; + Device deviceForEpocRoot(const QString &root) const; static QString cleanedRootPath(const QString &deviceRoot); signals: diff --git a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp index 4b16410e61b9a74458e3cc1a59d58060d3de0854..0c9084c88ddd84c75e6b07448627111eab5c006f 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp @@ -177,6 +177,7 @@ void S60Manager::updateQtVersions() deviceVersion->setName(deviceVersion->name().arg(deviceVersion->qtVersionString())); versionsToAdd.append(deviceVersion); } + deviceVersion->setS60SDKDirectory(device.epocRoot); } // remove old autodetected versions foreach (QtVersion *version, versions) { @@ -202,8 +203,9 @@ ProjectExplorer::ToolChain *S60Manager::createGCCEToolChain(const Qt4ProjectMana return new GCCEToolChain(deviceForQtVersion(version)); } -ProjectExplorer::ToolChain *S60Manager::createRVCTToolChain(const Qt4ProjectManager::QtVersion *version, - ProjectExplorer::ToolChain::ToolChainType type) const +ProjectExplorer::ToolChain *S60Manager::createRVCTToolChain( + const Qt4ProjectManager::QtVersion *version, + ProjectExplorer::ToolChain::ToolChainType type) const { return new RVCTToolChain(deviceForQtVersion(version), type); } @@ -215,15 +217,19 @@ S60Devices::Device S60Manager::deviceForQtVersion(const Qt4ProjectManager::QtVer if (version->isAutodetected()) deviceId = deviceIdFromDetectionSource(version->autodetectionSource()); if (deviceId.isEmpty()) { // it's not an s60 autodetected version - // have a look if we find the device root anyhow - QString qtPath = version->versionInfo().value("QT_INSTALL_DATA"); - if (QFile::exists(QString::fromLatin1("%1/epoc32").arg(qtPath))) { - device.epocRoot = qtPath; - device.toolsRoot = device.epocRoot; - device.qt = device.epocRoot; - device.isDefault = false; - device.name = QString::fromLatin1("SDK"); - device.id = QString::fromLatin1("SDK"); + // try to find a device entry belonging to the root given in Qt prefs + QString sdkRoot = version->s60SDKDirectory(); + device = m_devices->deviceForEpocRoot(sdkRoot); + if (device.epocRoot.isEmpty()) { // no device found + // check if we can construct a dummy one + if (QFile::exists(QString::fromLatin1("%1/epoc32").arg(sdkRoot))) { + device.epocRoot = sdkRoot; + device.toolsRoot = device.epocRoot; + device.qt = QFileInfo(QFileInfo(version->qmakeCommand()).path()).path(); + device.isDefault = false; + device.name = QString::fromLatin1("Manual"); + device.id = QString::fromLatin1("Manual"); + } } } else { device = m_devices->deviceForId(deviceId); diff --git a/src/plugins/qt4projectmanager/qtoptionspage.cpp b/src/plugins/qt4projectmanager/qtoptionspage.cpp index 70d83b6590d69ff00eccb897f38037cf11f2e450..0796dc44b9226f5be98c835265b11ef534264b6d 100644 --- a/src/plugins/qt4projectmanager/qtoptionspage.cpp +++ b/src/plugins/qt4projectmanager/qtoptionspage.cpp @@ -17,6 +17,8 @@ #include <QtCore/QDebug> #include <QtCore/QDir> #include <QtCore/QDateTime> +#include <QtGui/QHelpEvent> +#include <QtGui/QToolTip> using namespace Qt4ProjectManager; using namespace Qt4ProjectManager::Internal; @@ -121,7 +123,9 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<QtVersion *> ver m_ui->mingwPath->setExpectedKind(Utils::PathChooser::Directory); m_ui->mingwPath->setPromptDialogTitle(tr("Select the MinGW Directory")); m_ui->mwcPath->setExpectedKind(Utils::PathChooser::Directory); - m_ui->mwcPath->setPromptDialogTitle(tr("Select \"x86build\" Directory from Carbide Install")); + m_ui->mwcPath->setPromptDialogTitle(tr("Select Carbide Install Directory")); + m_ui->s60SDKPath->setExpectedKind(Utils::PathChooser::Directory); + m_ui->s60SDKPath->setPromptDialogTitle(tr("Select S60 SDK Root")); m_ui->addButton->setIcon(QIcon(Core::Constants::ICON_PLUS)); m_ui->delButton->setIcon(QIcon(Core::Constants::ICON_MINUS)); @@ -131,6 +135,7 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<QtVersion *> ver // setup parent items for auto-detected and manual versions m_ui->qtdirList->header()->setResizeMode(QHeaderView::ResizeToContents); QTreeWidgetItem *autoItem = new QTreeWidgetItem(m_ui->qtdirList); + m_ui->qtdirList->installEventFilter(this); autoItem->setText(0, tr("Auto-detected")); autoItem->setFirstColumnSpanned(true); QTreeWidgetItem *manualItem = new QTreeWidgetItem(m_ui->qtdirList); @@ -167,6 +172,8 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<QtVersion *> ver #ifdef QTCREATOR_WITH_S60 connect(m_ui->mwcPath, SIGNAL(changed(QString)), this, SLOT(updateCurrentMwcDirectory())); + connect(m_ui->s60SDKPath, SIGNAL(changed(QString)), + this, SLOT(updateCurrentS60SDKDirectory())); #endif connect(m_ui->addButton, SIGNAL(clicked()), @@ -196,6 +203,26 @@ QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<QtVersion *> ver updateState(); } +bool QtOptionsPageWidget::eventFilter(QObject *o, QEvent *e) +{ + // Set the items tooltip, which may cause costly initialization + // of QtVersion and must be up-to-date + if (o != m_ui->qtdirList || e->type() != QEvent::ToolTip) + return false; + QHelpEvent *helpEvent = static_cast<QHelpEvent *>(e); + const QPoint treePos = helpEvent->pos() - QPoint(0, m_ui->qtdirList->header()->height()); + QTreeWidgetItem *item = m_ui->qtdirList->itemAt(treePos); + if (!item) + return false; + const int index = indexForTreeItem(item); + if (index == -1) + return false; + const QString tooltip = m_versions.at(index)->toHtml(); + QToolTip::showText(helpEvent->globalPos(), tooltip, m_ui->qtdirList); + helpEvent->accept(); + return true; +} + int QtOptionsPageWidget::currentIndex() const { if (QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem()) @@ -367,6 +394,8 @@ void QtOptionsPageWidget::updateState() m_ui->nameEdit->setEnabled(enabled && !isAutodetected); m_ui->qmakePath->setEnabled(enabled && !isAutodetected); m_ui->mingwPath->setEnabled(enabled); + m_ui->mwcPath->setEnabled(enabled); + m_ui->s60SDKPath->setEnabled(enabled && !isAutodetected); const bool hasLog = enabled && !m_ui->qtdirList->currentItem()->data(2, Qt::UserRole).toString().isEmpty(); m_ui->showLogButton->setEnabled(hasLog); @@ -388,10 +417,12 @@ void QtOptionsPageWidget::makeMSVCVisible(bool visible) m_ui->msvcNotFoundLabel->setVisible(false); } -void QtOptionsPageWidget::makeMWCVisible(bool visible) +void QtOptionsPageWidget::makeS60Visible(bool visible) { m_ui->mwcLabel->setVisible(visible); m_ui->mwcPath->setVisible(visible); + m_ui->s60SDKLabel->setVisible(visible); + m_ui->s60SDKPath->setVisible(visible); } void QtOptionsPageWidget::showEnvironmentPage(QTreeWidgetItem *item) @@ -401,7 +432,7 @@ void QtOptionsPageWidget::showEnvironmentPage(QTreeWidgetItem *item) if (index < 0) { makeMSVCVisible(false); makeMingwVisible(false); - makeMWCVisible(false); + makeS60Visible(false); return; } m_ui->errorLabel->setText(""); @@ -409,12 +440,12 @@ void QtOptionsPageWidget::showEnvironmentPage(QTreeWidgetItem *item) if (types.contains(ProjectExplorer::ToolChain::MinGW)) { makeMSVCVisible(false); makeMingwVisible(true); - makeMWCVisible(false); + makeS60Visible(false); m_ui->mingwPath->setPath(m_versions.at(index)->mingwDirectory()); } else if (types.contains(ProjectExplorer::ToolChain::MSVC) || types.contains(ProjectExplorer::ToolChain::WINCE)){ makeMSVCVisible(false); makeMingwVisible(false); - makeMWCVisible(false); + makeS60Visible(false); QStringList msvcEnvironments = ProjectExplorer::ToolChain::availableMSVCVersions(); if (msvcEnvironments.count() == 0) { m_ui->msvcLabel->setVisible(true); @@ -432,16 +463,20 @@ void QtOptionsPageWidget::showEnvironmentPage(QTreeWidgetItem *item) m_ui->msvcComboBox->blockSignals(block); } #ifdef QTCREATOR_WITH_S60 - } else if (types.contains(ProjectExplorer::ToolChain::WINSCW)) { + } else if (types.contains(ProjectExplorer::ToolChain::WINSCW) + || types.contains(ProjectExplorer::ToolChain::RVCT_ARMV5) + || types.contains(ProjectExplorer::ToolChain::RVCT_ARMV6) + || types.contains(ProjectExplorer::ToolChain::GCCE)) { makeMSVCVisible(false); makeMingwVisible(false); - makeMWCVisible(true); + makeS60Visible(true); m_ui->mwcPath->setPath(m_versions.at(index)->mwcDirectory()); + m_ui->s60SDKPath->setPath(m_versions.at(index)->s60SDKDirectory()); #endif } else if (types.contains(ProjectExplorer::ToolChain::INVALID)) { makeMSVCVisible(false); makeMingwVisible(false); - makeMWCVisible(false); + makeS60Visible(false); if (!m_versions.at(index)->isInstalled()) m_ui->errorLabel->setText(tr("The Qt Version identified by %1 is not installed. Run make install") .arg(QDir::toNativeSeparators(m_versions.at(index)->qmakeCommand()))); @@ -450,7 +485,7 @@ void QtOptionsPageWidget::showEnvironmentPage(QTreeWidgetItem *item) } else { //ProjectExplorer::ToolChain::GCC makeMSVCVisible(false); makeMingwVisible(false); - makeMWCVisible(false); + makeS60Visible(false); m_ui->errorLabel->setText(tr("Found Qt version %1, using mkspec %2") .arg(m_versions.at(index)->qtVersionString(), m_versions.at(index)->mkspec())); @@ -458,7 +493,7 @@ void QtOptionsPageWidget::showEnvironmentPage(QTreeWidgetItem *item) } else { makeMSVCVisible(false); makeMingwVisible(false); - makeMWCVisible(false); + makeS60Visible(false); } } @@ -654,6 +689,15 @@ void QtOptionsPageWidget::updateCurrentMwcDirectory() return; m_versions[currentItemIndex]->setMwcDirectory(m_ui->mwcPath->path()); } +void QtOptionsPageWidget::updateCurrentS60SDKDirectory() +{ + QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem(); + Q_ASSERT(currentItem); + int currentItemIndex = indexForTreeItem(currentItem); + if (currentItemIndex < 0) + return; + m_versions[currentItemIndex]->setS60SDKDirectory(m_ui->s60SDKPath->path()); +} #endif QList<QSharedPointerQtVersion> QtOptionsPageWidget::versions() const diff --git a/src/plugins/qt4projectmanager/qtoptionspage.h b/src/plugins/qt4projectmanager/qtoptionspage.h index 9581f37d425351f125c01792a27cde94b84ac9b7..4e1f2b49fe82f446ea9ec0385f2d24b46627a48e 100644 --- a/src/plugins/qt4projectmanager/qtoptionspage.h +++ b/src/plugins/qt4projectmanager/qtoptionspage.h @@ -82,6 +82,8 @@ public: int defaultVersion() const; void finish(); + virtual bool eventFilter(QObject *o, QEvent *e); + private: void showEnvironmentPage(QTreeWidgetItem * item); void fixQtVersionName(int index); @@ -109,7 +111,7 @@ private slots: void updateState(); void makeMingwVisible(bool visible); void makeMSVCVisible(bool visible); - void makeMWCVisible(bool visible); + void makeS60Visible(bool visible); void onQtBrowsed(); void onMingwBrowsed(); void defaultChanged(int index); @@ -118,6 +120,7 @@ private slots: void updateCurrentMingwDirectory(); #ifdef QTCREATOR_WITH_S60 void updateCurrentMwcDirectory(); + void updateCurrentS60SDKDirectory(); #endif void msvcVersionChanged(); void buildDebuggingHelper(); diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index e600e085fd70809ecb89385d964a6c6ce557d228..beefffe52983f259fa9fa1e26057840535d5210a 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -54,6 +54,7 @@ #include <QtCore/QSettings> #include <QtCore/QTime> #include <QtCore/QTimer> +#include <QtCore/QTextStream> #include <QtGui/QApplication> #include <QtGui/QDesktopServices> @@ -129,6 +130,7 @@ QtVersionManager::QtVersionManager() version->setMsvcVersion(s->value("msvcVersion").toString()); #ifdef QTCREATOR_WITH_S60 version->setMwcDirectory(s->value("MwcDirectory").toString()); + version->setS60SDKDirectory(s->value("S60SDKDirectory").toString()); #endif m_versions.append(version); } @@ -248,6 +250,7 @@ void QtVersionManager::writeVersionsIntoSettings() s->setValue("autodetectionSource", version->autodetectionSource()); #ifdef QTCREATOR_WITH_S60 s->setValue("MwcDirectory", version->mwcDirectory()); + s->setValue("S60SDKDirectory", version->s60SDKDirectory()); #endif } s->endArray(); @@ -487,6 +490,43 @@ QtVersion::~QtVersion() } +QString QtVersion::toHtml() const +{ + QString rc; + QTextStream str(&rc); + str << "<html></head><body><table>"; + str << "<tr><td><b>" << QtVersionManager::tr("Name:") + << "</b></td><td>" << name() << "</td></tr>"; + str << "<tr><td><b>" << QtVersionManager::tr("Source:") + << "</b></td><td>" << sourcePath() << "</td></tr>"; + str << "<tr><td><b>" << QtVersionManager::tr("mkspec:") + << "</b></td><td>" << mkspec() << "</td></tr>"; + str << "<tr><td><b>" << QtVersionManager::tr("qmake:") + << "</b></td><td>" << m_qmakeCommand << "</td></tr>"; + updateVersionInfo(); + if (m_defaultConfigIsDebug || m_defaultConfigIsDebugAndRelease) { + str << "<tr><td><b>" << QtVersionManager::tr("Default:") << "</b></td><td>"; + if (m_defaultConfigIsDebug) + str << "debug"; + if (m_defaultConfigIsDebugAndRelease) + str << "default_and_release"; + str << "</td></tr>"; + } // default config. + str << "<tr><td><b>" << QtVersionManager::tr("Version:") + << "</b></td><td>" << qtVersionString() << "</td></tr>"; + if (hasDebuggingHelper()) + str << "<tr><td><b>" << QtVersionManager::tr("Debugging helper:") + << "</b></td><td>" << debuggingHelperLibrary() << "</td></tr>"; + const QHash<QString,QString> vInfo = versionInfo(); + if (!vInfo.isEmpty()) { + const QHash<QString,QString>::const_iterator vcend = vInfo.constEnd(); + for (QHash<QString,QString>::const_iterator it = vInfo.constBegin(); it != vcend; ++it) + str << "<tr><td><pre>" << it.key() << "</pre></td><td>" << it.value() << "</td></tr>"; + } + str << "<table></body></html>"; + return rc; +} + QString QtVersion::name() const { return m_name; @@ -1185,6 +1225,15 @@ void QtVersion::setMwcDirectory(const QString &directory) { m_mwcDirectory = directory; } +QString QtVersion::s60SDKDirectory() const +{ + return m_s60SDKDirectory; +} + +void QtVersion::setS60SDKDirectory(const QString &directory) +{ + m_s60SDKDirectory = directory; +} #endif QString QtVersion::mingwDirectory() const @@ -1308,7 +1357,7 @@ bool QtVersion::isQt64Bit() const #ifdef Q_OS_WIN32 # ifdef __GNUC__ // MinGW lacking some definitions/winbase.h # define SCS_64BIT_BINARY 6 -# endif +# endif DWORD binaryType = 0; bool success = GetBinaryTypeW(reinterpret_cast<const TCHAR*>(make.utf16()), &binaryType) != 0; if (success && binaryType == SCS_64BIT_BINARY) diff --git a/src/plugins/qt4projectmanager/qtversionmanager.h b/src/plugins/qt4projectmanager/qtversionmanager.h index cb26e49c13cba89bcec63d8ef20198bb13dc01c1..758a7aa63db1b773a824edf151c1bbea2d717212 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.h +++ b/src/plugins/qt4projectmanager/qtversionmanager.h @@ -95,6 +95,8 @@ public: #ifdef QTCREATOR_WITH_S60 QString mwcDirectory() const; void setMwcDirectory(const QString &directory); + QString s60SDKDirectory() const; + void setS60SDKDirectory(const QString &directory); #endif QString mingwDirectory() const; void setMingwDirectory(const QString &directory); @@ -130,6 +132,9 @@ public: }; QmakeBuildConfig defaultBuildConfig() const; + + QString toHtml() const; + private: QList<QSharedPointer<ProjectExplorer::ToolChain> > toolChains() const; static int getUniqueId(); @@ -149,6 +154,7 @@ private: bool m_hasDebuggingHelper; #ifdef QTCREATOR_WITH_S60 QString m_mwcDirectory; + QString m_s60SDKDirectory; #endif mutable bool m_mkspecUpToDate; diff --git a/src/plugins/qt4projectmanager/qtversionmanager.ui b/src/plugins/qt4projectmanager/qtversionmanager.ui index 81d7156c4bc0b6098276227fbaa1795fbc80de65..2f0a1dc840fd6986353016cf002763e9850b89f2 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.ui +++ b/src/plugins/qt4projectmanager/qtversionmanager.ui @@ -100,7 +100,7 @@ p, li { white-space: pre-wrap; } </item> </layout> </item> - <item row="6" column="1"> + <item row="7" column="1"> <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> <widget class="QLabel" name="debuggingHelperStateLabel"> @@ -193,29 +193,39 @@ p, li { white-space: pre-wrap; } </property> </widget> </item> - <item row="6" column="0"> - <widget class="QLabel" name="debuggingHelperLabel"> + <item row="5" column="0"> + <widget class="QLabel" name="s60SDKLabel"> <property name="text"> - <string>Debugging Helper:</string> + <string>S60 SDK:</string> </property> </widget> </item> - <item row="7" column="1"> - <widget class="QLabel" name="errorLabel"> + <item row="5" column="1"> + <widget class="Utils::PathChooser" name="s60SDKPath" native="true"/> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="mwcLabel"> <property name="text"> - <string/> + <string>Carbide Directory:</string> </property> </widget> </item> - <item row="5" column="0"> - <widget class="QLabel" name="mwcLabel"> + <item row="6" column="1"> + <widget class="Utils::PathChooser" name="mwcPath" native="true"/> + </item> + <item row="7" column="0"> + <widget class="QLabel" name="debuggingHelperLabel"> <property name="text"> - <string>MWC Directory:</string> + <string>Debugging Helper:</string> </property> </widget> </item> - <item row="5" column="1"> - <widget class="Utils::PathChooser" name="mwcPath" native="true"/> + <item row="8" column="1"> + <widget class="QLabel" name="errorLabel"> + <property name="text"> + <string/> + </property> + </widget> </item> </layout> </widget> diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 440acd8456d3e74d056266a12f11dfcb8a2642a8..e9beb84e1568d44b0083282e48c3e1dc30c910dc 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -4651,7 +4651,8 @@ void BaseTextEditor::insertFromMimeData(const QMimeData *source) || text.endsWith(QChar::ParagraphSeparator) || text.endsWith(QLatin1Char('\r'))); - if (hasFinalNewline) // since we'll add a final newline, preserve current line's indentation + if (insertAtBeginningOfLine + && hasFinalNewline) // since we'll add a final newline, preserve current line's indentation cursor.setPosition(cursor.block().position()); int cursorPosition = cursor.position(); diff --git a/src/plugins/welcome/communitywelcomepagewidget.cpp b/src/plugins/welcome/communitywelcomepagewidget.cpp index 5b54f23cb7dd25be88d33785e31b5713587d2cb4..a6ffff280c9cbd197128b424dd5c7f97cb1c8372 100644 --- a/src/plugins/welcome/communitywelcomepagewidget.cpp +++ b/src/plugins/welcome/communitywelcomepagewidget.cpp @@ -32,11 +32,12 @@ #include "rssfetcher.h" +#include <QtCore/QMap> #include <QtGui/QDesktopServices> +#include <QtGui/QTreeWidgetItem> namespace Welcome { namespace Internal { - CommunityWelcomePageWidget::CommunityWelcomePageWidget(QWidget *parent) : QWidget(parent), m_rssFetcher(new RSSFetcher(7)), @@ -54,13 +55,23 @@ CommunityWelcomePageWidget::CommunityWelcomePageWidget(QWidget *parent) : //: Add localized feed here only if one exists m_rssFetcher->fetch(QUrl(tr("http://labs.trolltech.com/blogs/feed"))); - ui->sitesTreeWidget->addItem(tr("Qt Home"), QLatin1String("http://qt.nokia.com")); - ui->sitesTreeWidget->addItem(tr("Qt Labs"), QLatin1String("http://labs.trolltech.com")); - ui->sitesTreeWidget->addItem(tr("Qt Git Hosting"), QLatin1String("http://qt.gitorious.org")); - ui->sitesTreeWidget->addItem(tr("Qt Centre"), QLatin1String("http://www.qtcentre.org")); - ui->sitesTreeWidget->addItem(tr("Qt for Symbian at Forum Nokia"), QLatin1String("http://discussion.forum.nokia.com/forum/forumdisplay.php?f=196")); + QMap<QString, QString> sites; + sites[tr("Qt Home")] = QLatin1String("http://qt.nokia.com"); + sites[tr("Qt Labs")] = QLatin1String("http://labs.qt.nokia.com"); + sites[tr("Qt Git Hosting")] = QLatin1String("http://qt.gitorious.org"); + sites[tr("Qt Centre")] = QLatin1String("http://www.qtcentre.org"); + sites[tr("Qt Apps")] = QLatin1String("http://www.qt-apps.org"); + sites[tr("Qt for Symbian at Forum Nokia")] = QLatin1String("http://discussion.forum.nokia.com/forum/forumdisplay.php?f=196"); + + QMapIterator<QString, QString> it(sites); + while (it.hasNext()) { + it.next(); + ui->sitesTreeWidget->addItem(it.key(), it.value(), it.value()); + } + } + CommunityWelcomePageWidget::~CommunityWelcomePageWidget() { delete m_rssFetcher; diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h index 9e570d2c1afeb5c326250c0b2e0895fa887382c5..9616f51780df1e4637c0802fb7d9b61b5df80002 100644 --- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h +++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h @@ -54,6 +54,8 @@ # if defined(CPLUSPLUS_BUILD_LIB) # define CPLUSPLUS_EXPORT Q_DECL_EXPORT +# elif defined(CPLUSPLUS_BUILD_STATIC_LIB) +# define CPLUSPLUS_EXPORT # else # define CPLUSPLUS_EXPORT Q_DECL_IMPORT # endif diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp index 6a81784360a2f59bb6eeeea9b38d0e7f9529d3bd..7e7d01d90718b85282653ceebe0a5d54d44da2c1 100644 --- a/src/shared/cplusplus/CheckDeclaration.cpp +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -190,6 +190,7 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast) fun->setScope(_scope); fun->setName(name); fun->setMethodKey(semantic()->currentMethodKey()); + fun->setVirtual(ty.isVirtual()); if (isQ_SIGNAL) fun->setMethodKey(Function::SignalMethod); else if (isQ_SLOT) @@ -281,6 +282,7 @@ bool CheckDeclaration::visit(FunctionDefinitionAST *ast) } Function *fun = funTy->asFunctionType(); + fun->setVirtual(ty.isVirtual()); fun->setStartOffset(tokenAt(ast->firstToken()).offset); fun->setEndOffset(tokenAt(ast->lastToken()).offset); if (ast->declarator) diff --git a/src/shared/cplusplus/FullySpecifiedType.cpp b/src/shared/cplusplus/FullySpecifiedType.cpp index 578c6c9b7d66c9e802ab1385a34bdf9abb6550ea..a9063fda67fa906ec23e6cbaf454ae17ee0890c3 100644 --- a/src/shared/cplusplus/FullySpecifiedType.cpp +++ b/src/shared/cplusplus/FullySpecifiedType.cpp @@ -80,6 +80,10 @@ FullySpecifiedType FullySpecifiedType::qualifiedType() const ty.setExtern(false); ty.setMutable(false); ty.setTypedef(false); + + ty.setInline(false); + ty.setVirtual(false); + ty.setExplicit(false); return ty; } @@ -209,4 +213,19 @@ FullySpecifiedType FullySpecifiedType::simplified() const return *this; } +void FullySpecifiedType::copySpecifiers(const FullySpecifiedType &type) +{ + // class storage specifiers + f._isFriend = type.f._isFriend; + f._isRegister = type.f._isRegister; + f._isStatic = type.f._isStatic; + f._isExtern = type.f._isExtern; + f._isMutable = type.f._isMutable; + f._isTypedef = type.f._isTypedef; + + // function specifiers + f._isInline = type.f._isInline; + f._isVirtual = type.f._isVirtual; + f._isExplicit = type.f._isExplicit; +} diff --git a/src/shared/cplusplus/FullySpecifiedType.h b/src/shared/cplusplus/FullySpecifiedType.h index 6c9f83d9145d616c84c3eac79e34802a9326e2e8..5aea04dca18253d12aa2a42300c8bb404e5595c1 100644 --- a/src/shared/cplusplus/FullySpecifiedType.h +++ b/src/shared/cplusplus/FullySpecifiedType.h @@ -121,6 +121,8 @@ public: FullySpecifiedType simplified() const; + void copySpecifiers(const FullySpecifiedType &type); + private: Type *_type; struct Flags { diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index 5a0bff45eb8378e1ae3b62044ae101ac5ae2cd8c..8abd64b1e630d2b96186244cab2b1e5d961d9c35 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -8,24 +8,9 @@ class tst_Preprocessor: public QObject Q_OBJECT private Q_SLOTS: - void pp_with_no_client(); - void unfinished_function_like_macro_call(); }; -void tst_Preprocessor::pp_with_no_client() -{ - Client *client = 0; // no client. - Environment env; - - Preprocessor preprocess(client, &env); - QByteArray preprocessed = preprocess(QLatin1String("<stdin>"), - QByteArray("\n#define foo(a,b) a + b" - "\nfoo(1, 2)\n")); - QByteArray expected = "1 + 2"; - QCOMPARE(preprocessed.trimmed(), expected); -} - void tst_Preprocessor::unfinished_function_like_macro_call() { Client *client = 0; // no client. @@ -35,8 +20,8 @@ void tst_Preprocessor::unfinished_function_like_macro_call() QByteArray preprocessed = preprocess(QLatin1String("<stdin>"), QByteArray("\n#define foo(a,b) a + b" "\nfoo(1, 2\n")); - QByteArray expected = "foo"; - QCOMPARE(preprocessed.trimmed(), expected); + + QCOMPARE(preprocessed.trimmed(), QByteArray("foo")); } QTEST_APPLESS_MAIN(tst_Preprocessor) diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index 827a227f053db188aa0c4f2505f4d9ba2a7f193f..6da954ae92fceceeed6bd2c676c7c12a806ebdf2 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -408,12 +408,12 @@ void tst_Semantic::template_instance_1() QVERIFY(decl); GenTemplateInstance::Substitution subst; - Name *nameTp = control.nameId(control.findOrInsertIdentifier("_Tp")); + Identifier *nameTp = control.findOrInsertIdentifier("_Tp"); FullySpecifiedType intTy(control.integerType(IntegerType::Int)); subst.append(qMakePair(nameTp, intTy)); GenTemplateInstance inst(&control, subst); - FullySpecifiedType genTy = inst(decl->type()); + FullySpecifiedType genTy = inst(decl); Overview oo; oo.setShowReturnTypes(true); diff --git a/tests/auto/cplusplus/shared/shared.pri b/tests/auto/cplusplus/shared/shared.pri index 80dab035ba8f6b391b20a2ad86f9146b3ac45772..9b173daa6137a0b88ef93efd124971a6015ff365 100644 --- a/tests/auto/cplusplus/shared/shared.pri +++ b/tests/auto/cplusplus/shared/shared.pri @@ -1,4 +1,4 @@ - +DEFINES+=CPLUSPLUS_BUILD_STATIC_LIB INCLUDEPATH += $$PWD/../../../../src/shared/cplusplus INCLUDEPATH += $$PWD/../../../../src/libs/cplusplus DEPENDPATH += $$INCLUDEPATH . diff --git a/tests/auto/debugger/gdb.pro b/tests/auto/debugger/gdb.pro new file mode 100644 index 0000000000000000000000000000000000000000..7f1d52a537255c111cb15286325d611b7be38537 --- /dev/null +++ b/tests/auto/debugger/gdb.pro @@ -0,0 +1,15 @@ +QT -= gui +QT += testlib + +UTILSDIR = ../../../src/libs + +DEBUGGERDIR = ../../../src/plugins/debugger + +INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR + +SOURCES += \ + tst_gdb.cpp \ + $$DEBUGGERDIR/gdb/gdbmi.cpp \ + +TARGET = tst_$$TARGET + diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 7dc603f664a0c57eda7e49eaad354d12d0fd9c00..eff6f97dbd211e7a171fb569d78a206035404141 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -10,6 +10,12 @@ #include <QtTest/QtTest> //#include <QtTest/qtest_gui.h> +#if (QT_POINTER_SIZE==4) +# define POINTER_PRINTFORMAT "0x%x" +#else +# define POINTER_PRINTFORMAT "0x%lx" +#endif + #undef NS #ifdef QT_NAMESPACE # define STRINGIFY0(s) #s @@ -387,7 +393,7 @@ static void testDumper(QByteArray expected0, const void *data, QByteArray outert extraInt0, extraInt1, extraInt2, extraInt3); QString expected(expected0); char buf[100]; - sprintf(buf, "%p", data); + sprintf(buf, POINTER_PRINTFORMAT, (uintptr_t)data); if ((!expected.startsWith('t') && !expected.startsWith('f')) || expected.startsWith("type")) expected = "tiname='$I',addr='$A'," + expected; @@ -417,7 +423,7 @@ static void testDumper(QByteArray expected0, const void *data, QByteArray outert QByteArray str(const void *p) { char buf[100]; - sprintf(buf, "%p", p); + sprintf(buf, POINTER_PRINTFORMAT, (uintptr_t)p); return buf; } @@ -880,7 +886,7 @@ void tst_Debugger::dumpQByteArray() &ba, NS"QByteArray", true); // Case 5: Regular and special characters and the replacement character. - ba = QByteArray("abc\a\n\r\e\'\"?"); + ba = QByteArray("abc\a\n\r\033\'\"?"); testDumper("value='YWJjBwoNGyciPw==',valueencoded='1',type='"NS"QByteArray'," "numchild='10',childtype='char',childnumchild='0',children=[" "{value='61 (97 'a')'},{value='62 (98 'b')'}," diff --git a/tests/auto/debugger/tst_gdb.cpp b/tests/auto/debugger/tst_gdb.cpp index f40b0756c7d5a2b5e7d722e6972516029e7f56fd..034e53221c192487f52370b72e3dde77040f2e55 100644 --- a/tests/auto/debugger/tst_gdb.cpp +++ b/tests/auto/debugger/tst_gdb.cpp @@ -194,6 +194,8 @@ private slots: void dumpQWeakPointer(); void dumpQVector(); + void dumpQHash(); + public slots: void dumperCompatibility(); #if 0 @@ -203,7 +205,6 @@ public slots: void dumpQDir(); void dumpQFile(); void dumpQFileInfo(); - void dumpQHash(); void dumpQHashNode(); void dumpQImage(); void dumpQImageData(); @@ -2557,6 +2558,84 @@ void tst_Gdb::dumpQWeakPointerHelper(QWeakPointer<T> &ptr) #endif } +///////////////////////////// QHash<QString, QString> ////////////////////////////// + +void dumpQHash_QString_QString() +{ + /* A */ QHash<QString, QString> h; + /* B */ h["hello"] = "world"; + /* C */ h["foo"] = "bar"; + /* D */ (void) 0; +} + +void dumpQHash_int_int() +{ + /* A */ QHash<int, int> h; + /* B */ h[43] = 44; + /* C */ h[45] = 46; + /* D */ (void) 0; +} + +void tst_Gdb::dumpQHash() +{ + // Need to check the following combinations: + // int-key optimization, small value + //struct NodeOS { void *next; uint k; uint v; } nodeOS + // int-key optimiatzion, large value + //struct NodeOL { void *next; uint k; void *v; } nodeOL + // no optimization, small value + //struct NodeNS + { void *next; uint h; uint k; uint v; } nodeNS + // no optimization, large value + //struct NodeNL { void *next; uint h; uint k; void *v; } nodeNL + // complex key + //struct NodeL { void *next; uint h; void *k; void *v; } nodeL + + prepare("dumpQHash_int_int"); + if (checkUninitialized) + run("A","{iname='local.h',addr='-',name='h'," + "type='"NS"QHash<int, int>',value='<not in scope>'," + "numchild='0'}"); + next(); + next(); + next(); + run("D","{iname='local.h',addr='-',name='h'," + "type='"NS"QHash<int, int>',value='<2 items>',numchild='2'," + "childtype='int',childnumchild='0',children=[" + "{name='43',value='44'}," + "{name='45',value='46'}]}", + "local.h"); + + prepare("dumpQHash_QString_QString"); + if (checkUninitialized) + run("A","{iname='local.h',addr='-',name='h'," + "type='"NS"QHash<"NS"QString, "NS"QString>',value='<not in scope>'," + "numchild='0'}"); + next(); + //run("B","{iname='local.h',addr='-',name='h'," + // "type='"NS"QHash<"NS"QString, "NS"QString>',value='<0 items>'," + // "numchild='0'}"); + next(); + next(); + //run("D","{iname='local.h',addr='-',name='h'," + // "type='"NS"QHash<"NS"QString, "NS"QString>',value='<2 items>'," + // "numchild='2'}"); + run("D","{iname='local.h',addr='-',name='h'," + "type='"NS"QHash<"NS"QString, "NS"QString>',value='<2 items>'," + "numchild='2',childtype='"NS"QHashNode<"NS"QString, "NS"QString>'," + "children=[" + "{value=' ',numchild='2',children=[{name='key',valueencoded='7'," + "value='66006f006f00',numchild='0'}," + "{name='value',valueencoded='7'," + "value='620061007200',numchild='0'}]}," + "{value=' ',numchild='2',children=[{name='key',valueencoded='7'," + "value='680065006c006c006f00',numchild='0'}," + "{name='value',valueencoded='7'," + "value='77006f0072006c006400',numchild='0'}]}" + "]}", + "local.h,local.h.0,local.h.1"); +} + + ///////////////////////////// QList<int> ///////////////////////////////// void dumpQList_int() diff --git a/tests/auto/fakevim/fakevim.pro b/tests/auto/fakevim/fakevim.pro index a4aaea078ed29b2f350d81243cd758280ab2f397..84c1029e3a62fc76eb962a3f952f696305a9168c 100644 --- a/tests/auto/fakevim/fakevim.pro +++ b/tests/auto/fakevim/fakevim.pro @@ -1,6 +1,9 @@ QT += testlib +# Defines import symbol as empty +DEFINES+=QTCREATOR_UTILS_STATIC_LIB + FAKEVIMDIR = ../../../src/plugins/fakevim UTILSDIR = ../../../src/libs diff --git a/tests/manual/preprocessor/main.cpp b/tests/manual/preprocessor/main.cpp index 64de2e56f549c9e2b477b41a0996ccec7aceb6be..2aaecb0027d8d1ac4c0ae3afdef1611096ca6f0b 100644 --- a/tests/manual/preprocessor/main.cpp +++ b/tests/manual/preprocessor/main.cpp @@ -69,9 +69,15 @@ public: #endif } + virtual void passedMacroDefinitionCheck(unsigned, const Macro &) + { } + + virtual void failedMacroDefinitionCheck(unsigned, const QByteArray &) + { } + virtual void startExpandingMacro(unsigned, const Macro &, const QByteArray &, - const QVector<MacroArgumentReference> &) + bool, const QVector<MacroArgumentReference> &) { } virtual void stopExpandingMacro(unsigned, const Macro &) @@ -84,11 +90,33 @@ public: { } }; +int make_depend(QCoreApplication *app); + + int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); - QStringList todo = app.arguments(); + QStringList args = app.arguments(); + args.removeFirst(); + + foreach (const QString &fileName, args) { + QFile file(fileName); + if (file.open(QFile::ReadOnly)) { + QTextStream in(&file); + const QString source = in.readAll(); + + Environment env; + Preprocessor pp(/*client=*/ 0, &env); + const QByteArray preprocessedCode = pp(fileName, source); + std::cout << preprocessedCode.constData(); + } + } +} + +int make_depend(QCoreApplication *app) +{ + QStringList todo = app->arguments(); todo.removeFirst(); if (todo.isEmpty())