From cbcc2e518d7365f18211a6baecbaafb0b9bcce27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Fri, 13 Feb 2009 16:29:30 +0100 Subject: [PATCH 1/8] Don't move cursor on collapse/uncollapse When the cursor isn't within the block that's being collapsed, it shouldn't be moved. When it is, it will now move upwards instead of to the start of the line. Reviewed-by: mae --- src/plugins/texteditor/basetexteditor.cpp | 10 +++++----- src/plugins/texteditor/basetexteditor_p.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 88e145a0e58..d5b088396a5 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -2504,14 +2504,13 @@ void BaseTextEditor::extraAreaMouseEvent(QMouseEvent *e) } } - if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonDblClick) { if (e->button() == Qt::LeftButton) { if (d->m_codeFoldingVisible && TextBlockUserData::canCollapse(cursor.block()) && !TextBlockUserData::hasClosingCollapseInside(cursor.block().next()) && collapseBox(cursor.block()).contains(e->pos())) { - setTextCursor(cursor); toggleBlockVisible(cursor.block()); + d->moveCursorVisible(false); } else if (d->m_marksVisible && e->pos().x() > markWidth) { QTextCursor selection = cursor; selection.setVisualNavigation(true); @@ -3392,15 +3391,16 @@ void BaseTextEditor::setIfdefedOutBlocks(const QList } -void BaseTextEditorPrivate::moveCursorVisible() +void BaseTextEditorPrivate::moveCursorVisible(bool ensureVisible) { QTextCursor cursor = q->textCursor(); if (!cursor.block().isVisible()) { cursor.setVisualNavigation(true); - cursor.movePosition(QTextCursor::PreviousBlock); + cursor.movePosition(QTextCursor::Up); q->setTextCursor(cursor); } - q->ensureCursorVisible(); + if (ensureVisible) + q->ensureCursorVisible(); } void BaseTextEditor::collapse() diff --git a/src/plugins/texteditor/basetexteditor_p.h b/src/plugins/texteditor/basetexteditor_p.h index 270b7444f42..9da5b27248c 100644 --- a/src/plugins/texteditor/basetexteditor_p.h +++ b/src/plugins/texteditor/basetexteditor_p.h @@ -218,7 +218,7 @@ public: QTextCursor m_findScope; QTextCursor m_selectBlockAnchor; - void moveCursorVisible(); + void moveCursorVisible(bool ensureVisible = true); }; } // namespace Internal From a0f521c7b68f9908abe9ac5d131c4fb5eab40ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Fri, 13 Feb 2009 17:33:59 +0100 Subject: [PATCH 2/8] Allow opening/closing debugger mode dockwidgets in locked mode There is no particular reason to disallow changing the visiblity of the dockwidgets in the debug mode in locked mode. --- src/plugins/debugger/debuggermanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 95b874a3f8a..f017cebccef 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -451,7 +451,7 @@ QDockWidget *DebuggerManager::createDockForWidget(QWidget *widget) { QDockWidget *dockWidget = new QDockWidget(widget->windowTitle(), m_mainWindow); dockWidget->setObjectName(widget->windowTitle()); - dockWidget->setFeatures(QDockWidget::NoDockWidgetFeatures); + dockWidget->setFeatures(QDockWidget::DockWidgetClosable); dockWidget->setTitleBarWidget(new QWidget(dockWidget)); dockWidget->setWidget(widget); connect(dockWidget->toggleViewAction(), SIGNAL(toggled(bool)), @@ -488,7 +488,7 @@ void DebuggerManager::setSimpleDockWidgetArrangement() void DebuggerManager::setLocked(bool locked) { const QDockWidget::DockWidgetFeatures features = - (locked) ? QDockWidget::NoDockWidgetFeatures : + (locked) ? QDockWidget::DockWidgetClosable : QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable; foreach (QDockWidget *dockWidget, m_dockWidgets) { From d98c141918c5f6d0618549893fbd15a199aa327d Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 13 Feb 2009 15:37:42 +0100 Subject: [PATCH 3/8] Improved the type pretty printer. (cherry picked from commit e801434799f8f4b25028f63c2595bd810277edb7) --- src/libs/cplusplus/Overview.cpp | 9 +- src/libs/cplusplus/Overview.h | 5 +- src/libs/cplusplus/TypePrettyPrinter.cpp | 240 +++++++++++++---------- src/libs/cplusplus/TypePrettyPrinter.h | 28 +-- 4 files changed, 156 insertions(+), 126 deletions(-) diff --git a/src/libs/cplusplus/Overview.cpp b/src/libs/cplusplus/Overview.cpp index 2494d11ec5e..0f973753d0b 100644 --- a/src/libs/cplusplus/Overview.cpp +++ b/src/libs/cplusplus/Overview.cpp @@ -68,6 +68,11 @@ bool Overview::showReturnTypes() const return _showReturnTypes; } +unsigned Overview::markArgument() const +{ + return _markArgument; +} + void Overview::setMarkArgument(unsigned position) { _markArgument = position; @@ -98,9 +103,5 @@ QString Overview::prettyType(const FullySpecifiedType &ty, const QString &name) const { TypePrettyPrinter pp(this); - pp.setMarkArgument(_markArgument); - pp.setShowArgumentNames(_showArgumentNames); - pp.setShowReturnTypes(_showReturnTypes); - pp.setShowFunctionSignatures(_showFunctionSignatures); return pp(ty, name); } diff --git a/src/libs/cplusplus/Overview.h b/src/libs/cplusplus/Overview.h index fa1f3cf919f..6918ee45ff8 100644 --- a/src/libs/cplusplus/Overview.h +++ b/src/libs/cplusplus/Overview.h @@ -57,7 +57,10 @@ public: bool showFunctionSignatures() const; void setShowFunctionSignatures(bool showFunctionSignatures); - void setMarkArgument(unsigned position); // 1-based + // 1-based + // ### rename + unsigned markArgument() const; + void setMarkArgument(unsigned position); QString operator()(Name *name) const { return prettyName(name); } diff --git a/src/libs/cplusplus/TypePrettyPrinter.cpp b/src/libs/cplusplus/TypePrettyPrinter.cpp index 6fd6a2cf245..6e46361b7f4 100644 --- a/src/libs/cplusplus/TypePrettyPrinter.cpp +++ b/src/libs/cplusplus/TypePrettyPrinter.cpp @@ -42,37 +42,12 @@ using namespace CPlusPlus; TypePrettyPrinter::TypePrettyPrinter(const Overview *overview) : _overview(overview), - _name(0), - _markArgument(0), - _showArgumentNames(false), - _showReturnTypes(false), - _showFunctionSignatures(true) + _name(0) { } TypePrettyPrinter::~TypePrettyPrinter() { } -bool TypePrettyPrinter::showArgumentNames() const -{ return _showArgumentNames; } - -void TypePrettyPrinter::setShowArgumentNames(bool showArgumentNames) -{ _showArgumentNames = showArgumentNames; } - -bool TypePrettyPrinter::showReturnTypes() const -{ return _showReturnTypes; } - -void TypePrettyPrinter::setShowReturnTypes(bool showReturnTypes) -{ _showReturnTypes = showReturnTypes; } - -bool TypePrettyPrinter::showFunctionSignatures() const -{ return _showFunctionSignatures; } - -void TypePrettyPrinter::setShowFunctionSignatures(bool showFunctionSignatures) -{ _showFunctionSignatures = showFunctionSignatures; } - -void TypePrettyPrinter::setMarkArgument(unsigned position) -{ _markArgument = position; } - const Overview *TypePrettyPrinter::overview() const { return _overview; } @@ -102,15 +77,16 @@ QString TypePrettyPrinter::operator()(const FullySpecifiedType &type, const QStr void TypePrettyPrinter::acceptType(const FullySpecifiedType &ty) { - if (ty.isConst()) - _text += QLatin1String("const "); - if (ty.isVolatile()) - _text += QLatin1String("volatile "); if (ty.isSigned()) - _text += QLatin1String("signed "); - if (ty.isUnsigned()) - _text += QLatin1String("unsigned "); + out(QLatin1String("signed ")); + + else if (ty.isUnsigned()) + out(QLatin1String("unsigned ")); + + const FullySpecifiedType previousFullySpecifiedType = _fullySpecifiedType; + _fullySpecifiedType = ty; accept(ty.type()); + _fullySpecifiedType = previousFullySpecifiedType; } QString TypePrettyPrinter::switchName(const QString &name) @@ -127,9 +103,9 @@ QString TypePrettyPrinter::switchText(const QString &name) return previousName; } -QList TypePrettyPrinter::switchPtrOperators(const QList &ptrOperators) +QList TypePrettyPrinter::switchPtrOperators(const QList &ptrOperators) { - QList previousPtrOperators = _ptrOperators; + QList previousPtrOperators = _ptrOperators; _ptrOperators = ptrOperators; return previousPtrOperators; } @@ -137,31 +113,53 @@ QList TypePrettyPrinter::switchPtrOperators(const QList &ptrOper void TypePrettyPrinter::applyPtrOperators(bool wantSpace) { for (int i = _ptrOperators.size() - 1; i != -1; --i) { - Type *op = _ptrOperators.at(i); + const FullySpecifiedType op = _ptrOperators.at(i); if (i == 0 && wantSpace) - _text += QLatin1Char(' '); + space(); - if (PointerType *ptrTy = op->asPointerType()) { - _text += QLatin1Char('*'); - if (ptrTy->elementType().isConst()) - _text += " const"; - if (ptrTy->elementType().isVolatile()) - _text += " volatile"; + if (op->isPointerType()) { + out(QLatin1Char('*')); + outCV(op); } else if (op->isReferenceType()) { - _text += QLatin1Char('&'); - } else if (PointerToMemberType *memPtrTy = op->asPointerToMemberType()) { - _text += QLatin1Char(' '); - _text += _overview->prettyName(memPtrTy->memberName()); - _text += QLatin1Char('*'); + out(QLatin1Char('&')); + } else if (const PointerToMemberType *memPtrTy = op->asPointerToMemberType()) { + space(); + out(_overview->prettyName(memPtrTy->memberName())); + out(QLatin1Char('*')); + outCV(op); } } } void TypePrettyPrinter::visit(VoidType *) { - _text += QLatin1String("void"); + out(QLatin1String("void")); + applyPtrOperators(); +} +void TypePrettyPrinter::visit(NamedType *type) +{ + out(overview()->prettyName(type->name())); + applyPtrOperators(); +} + +void TypePrettyPrinter::visit(Namespace *type) +{ + _text += overview()->prettyName(type->name()); + applyPtrOperators(); +} + +void TypePrettyPrinter::visit(Class *type) +{ + _text += overview()->prettyName(type->name()); + applyPtrOperators(); +} + + +void TypePrettyPrinter::visit(Enum *type) +{ + _text += overview()->prettyName(type->name()); applyPtrOperators(); } @@ -169,25 +167,25 @@ void TypePrettyPrinter::visit(IntegerType *type) { switch (type->kind()) { case IntegerType::Char: - _text += QLatin1String("char"); + out(QLatin1String("char")); break; case IntegerType::WideChar: - _text += QLatin1String("wchar_t"); + out(QLatin1String("wchar_t")); break; case IntegerType::Bool: - _text += QLatin1String("bool"); + out(QLatin1String("bool")); break; case IntegerType::Short: - _text += QLatin1String("short"); + out(QLatin1String("short")); break; case IntegerType::Int: - _text += QLatin1String("int"); + out(QLatin1String("int")); break; case IntegerType::Long: - _text += QLatin1String("long"); + out(QLatin1String("long")); break; case IntegerType::LongLong: - _text += QLatin1String("long long"); + out(QLatin1String("long long")); break; } @@ -198,13 +196,13 @@ void TypePrettyPrinter::visit(FloatType *type) { switch (type->kind()) { case FloatType::Float: - _text += QLatin1String("float"); + out(QLatin1String("float")); break; case FloatType::Double: - _text += QLatin1String("double"); + out(QLatin1String("double")); break; case FloatType::LongDouble: - _text += QLatin1String("long double"); + out(QLatin1String("long double")); break; } @@ -213,99 +211,135 @@ void TypePrettyPrinter::visit(FloatType *type) void TypePrettyPrinter::visit(PointerToMemberType *type) { - _ptrOperators.append(type); + outCV(type->elementType()); + space(); + + _ptrOperators.append(_fullySpecifiedType); acceptType(type->elementType()); } void TypePrettyPrinter::visit(PointerType *type) { - _ptrOperators.append(type); + outCV(type->elementType()); + space(); + + _ptrOperators.append(_fullySpecifiedType); acceptType(type->elementType()); } void TypePrettyPrinter::visit(ReferenceType *type) { - _ptrOperators.append(type); + outCV(type->elementType()); + space(); + + _ptrOperators.append(_fullySpecifiedType); acceptType(type->elementType()); } void TypePrettyPrinter::visit(ArrayType *type) { - _text += overview()->prettyType(type->elementType()); + out(overview()->prettyType(type->elementType())); if (! _ptrOperators.isEmpty()) { - _text += QLatin1Char('('); + out(QLatin1Char('(')); applyPtrOperators(false); if (! _name.isEmpty()) { - _text += _name; + out(_name); _name.clear(); } - _text += QLatin1Char(')'); + out(QLatin1Char(')')); } - _text += QLatin1String("[]"); -} - -void TypePrettyPrinter::visit(NamedType *type) -{ - _text += overview()->prettyName(type->name()); - applyPtrOperators(); + out(QLatin1String("[]")); } void TypePrettyPrinter::visit(Function *type) { - if (_showReturnTypes) - _text += _overview->prettyType(type->returnType()); + if (_overview->showReturnTypes()) + out(_overview->prettyType(type->returnType())); if (! _ptrOperators.isEmpty()) { - _text += QLatin1Char('('); + out(QLatin1Char('(')); applyPtrOperators(false); if (! _name.isEmpty()) { _text += _name; _name.clear(); } - _text += QLatin1Char(')'); - } else if (! _name.isEmpty() && _showFunctionSignatures) { - _text += QLatin1Char(' '); // ### fixme - _text += _name; + out(QLatin1Char(')')); + } else if (! _name.isEmpty() && _overview->showFunctionSignatures()) { + space(); + out(_name); _name.clear(); } - if (_showFunctionSignatures) { + if (_overview->showFunctionSignatures()) { Overview argumentText; - _text += QLatin1Char('('); + argumentText.setShowReturnTypes(true); + argumentText.setShowArgumentNames(false); + argumentText.setShowFunctionSignatures(true); + + out(QLatin1Char('(')); + for (unsigned index = 0; index < type->argumentCount(); ++index) { if (index != 0) - _text += QLatin1String(", "); + out(QLatin1String(", ")); if (Argument *arg = type->argumentAt(index)->asArgument()) { - if (index + 1 == _markArgument) - _text += QLatin1String(""); + if (index + 1 == _overview->markArgument()) + out(QLatin1String("")); + Name *name = 0; - if (_showArgumentNames) + + if (_overview->showArgumentNames()) name = arg->name(); - _text += argumentText(arg->type(), name); - if (index + 1 == _markArgument) - _text += QLatin1String(""); + + out(argumentText(arg->type(), name)); + + if (index + 1 == _overview->markArgument()) + out(QLatin1String("")); } } if (type->isVariadic()) - _text += QLatin1String("..."); + out(QLatin1String("...")); - _text += QLatin1Char(')'); - - if (type->isConst()) - _text += QLatin1String(" const"); - - if (type->isVolatile()) - _text += QLatin1String(" volatile"); + out(QLatin1Char(')')); + if (type->isConst() && type->isVolatile()) { + space(); + out("const volatile"); + } else if (type->isConst()) { + space(); + out("const"); + } else if (type->isVolatile()) { + space(); + out("volatile"); + } } } -void TypePrettyPrinter::visit(Namespace *type) -{ _text += overview()->prettyName(type->name()); } +void TypePrettyPrinter::space() +{ + if (_text.isEmpty()) + return; -void TypePrettyPrinter::visit(Class *type) -{ _text += overview()->prettyName(type->name()); } + const QChar ch = _text.at(_text.length() - 1); -void TypePrettyPrinter::visit(Enum *type) -{ _text += overview()->prettyName(type->name()); } + if (ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == QLatin1Char(')')) + _text += QLatin1Char(' '); +} + +void TypePrettyPrinter::out(const QString &text) +{ _text += text; } + +void TypePrettyPrinter::out(const QChar &ch) +{ _text += ch; } + +void TypePrettyPrinter::outCV(const FullySpecifiedType &ty) +{ + if (ty.isConst() && ty.isVolatile()) + out(QLatin1String("const volatile")); + + else if (ty.isConst()) + out(QLatin1String("const")); + + else if (ty.isVolatile()) + out(QLatin1String("volatile")); +} diff --git a/src/libs/cplusplus/TypePrettyPrinter.h b/src/libs/cplusplus/TypePrettyPrinter.h index 790999dc824..6191cf01af0 100644 --- a/src/libs/cplusplus/TypePrettyPrinter.h +++ b/src/libs/cplusplus/TypePrettyPrinter.h @@ -33,7 +33,8 @@ #ifndef TYPEPRETTYPRINTER_H #define TYPEPRETTYPRINTER_H -#include "TypeVisitor.h" +#include +#include #include #include @@ -50,23 +51,12 @@ public: const Overview *overview() const; - bool showArgumentNames() const; - void setShowArgumentNames(bool showArgumentNames); - - bool showReturnTypes() const; - void setShowReturnTypes(bool showReturnTypes); - - bool showFunctionSignatures() const; - void setShowFunctionSignatures(bool showFunctionSignatures); - - void setMarkArgument(unsigned position); // 1-based - QString operator()(const FullySpecifiedType &type); QString operator()(const FullySpecifiedType &type, const QString &name); protected: QString switchText(const QString &text = QString()); - QList switchPtrOperators(const QList &ptrOperators); + QList switchPtrOperators(const QList &ptrOperators); QString switchName(const QString &name); void applyPtrOperators(bool wantSpace = true); @@ -85,15 +75,17 @@ protected: virtual void visit(Class *type); virtual void visit(Enum *type); + void space(); + void out(const QString &text); + void out(const QChar &ch); + void outCV(const FullySpecifiedType &ty); + private: const Overview *_overview; QString _name; QString _text; - QList _ptrOperators; - unsigned _markArgument; - bool _showArgumentNames: 1; - bool _showReturnTypes: 1; - bool _showFunctionSignatures: 1; + FullySpecifiedType _fullySpecifiedType; + QList _ptrOperators; }; } // end of namespace CPlusPlus From 7c71b1bf38add9ae086d4af254ba97e94a3e518e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Mon, 16 Feb 2009 11:20:11 +0100 Subject: [PATCH 4/8] Fixed crash on updating function argument widget Crashed for example in the case of template instantiation. To make sure the Function* stays valid, we need to not only keep around the Snapshot but the whole LookupContext. Done with Roberto Raggi. --- src/plugins/cpptools/cppcodecompletion.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index bca1d576e9f..f06b88ec303 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -78,7 +78,7 @@ class FunctionArgumentWidget : public QLabel { public: FunctionArgumentWidget(); - void showFunctionHint(Function *functionSymbol, const Snapshot &snapshot); + void showFunctionHint(Function *functionSymbol, const LookupContext &context); protected: bool eventFilter(QObject *obj, QEvent *e); @@ -95,7 +95,7 @@ private: QFrame *m_popupFrame; Function *m_item; - Snapshot m_snapshot; + LookupContext m_context; }; class ConvertToCompletionItem: protected NameVisitor @@ -215,10 +215,10 @@ FunctionArgumentWidget::FunctionArgumentWidget() } void FunctionArgumentWidget::showFunctionHint(Function *functionSymbol, - const Snapshot &snapshot) + const LookupContext &context) { m_item = functionSymbol; - m_snapshot = snapshot; + m_context = context; m_startpos = m_editor->position(); // update the text @@ -1041,7 +1041,7 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item) QTC_ASSERT(function, return); m_functionArgumentWidget = new FunctionArgumentWidget(); - m_functionArgumentWidget->showFunctionHint(function, typeOfExpression.snapshot()); + m_functionArgumentWidget->showFunctionHint(function, typeOfExpression.lookupContext()); } } else if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT) { QString toInsert = item.m_text; From e539a9375b6279b84390ee3be3a1529b5b779b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Mon, 16 Feb 2009 14:54:41 +0100 Subject: [PATCH 5/8] Avoid inserting characters that are already there When completing, don't insert "();" characters when they're already there. Skip them instead. (cherry picked from commit 86427ecf62def3ae13caaf3f7785cdc0e95943d9) Conflicts: src/plugins/cpptools/cppcodecompletion.cpp --- src/plugins/cpptools/cppcodecompletion.cpp | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index f06b88ec303..0ff66aaa6ee 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -1052,11 +1052,14 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item) m_editor->replace(length, toInsert); } else { QString toInsert = item.m_text; + int extraLength = 0; //qDebug() << "current symbol:" << overview.prettyName(symbol->name()) //<< overview.prettyType(symbol->type()); if (m_autoInsertBraces && symbol) { + QString extraChars; + if (Function *function = symbol->type()->asFunction()) { // If the member is a function, automatically place the opening parenthesis, // except when it might take template parameters. @@ -1069,28 +1072,40 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item) } else if (function->templateParameterCount() != 0) { // If there are no arguments, then we need the template specification if (function->argumentCount() == 0) { - toInsert.append(QLatin1Char('<')); + extraChars += QLatin1Char('<'); } } else { - toInsert.append(QLatin1Char('(')); + extraChars += QLatin1Char('('); // If the function takes no arguments, automatically place the closing parenthesis if (function->argumentCount() == 0 || (function->argumentCount() == 1 && function->argumentAt(0)->type()->isVoidType())) { - toInsert.append(QLatin1Char(')')); + extraChars += QLatin1Char(')'); // If the function doesn't return anything, automatically place the semicolon, // unless we're doing a scope completion (then it might be function definition). if (function->returnType()->isVoidType() && m_completionOperator != T_COLON_COLON) { - toInsert.append(QLatin1Char(';')); + extraChars += QLatin1Char(';'); } } } } + + // Avoid inserting characters that are already there + for (int i = 0; i < extraChars.length(); ++i) { + const QChar a = extraChars.at(i); + const QChar b = m_editor->characterAt(m_editor->position() + i); + if (a == b) + ++extraLength; + else + break; + } + + toInsert += extraChars; } // Insert the remainder of the name - int length = m_editor->position() - m_startPosition; + int length = m_editor->position() - m_startPosition + extraLength; m_editor->setCurPos(m_startPosition); m_editor->replace(length, toInsert); } From 9aa86f91356630b3609ffc577c0232992dca3050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Wed, 4 Feb 2009 16:40:42 +0100 Subject: [PATCH 6/8] Completion for constructors used on initialization Deals with cases like "QString s(", but for the moment doesn't handle yet "QString const s(". Done with Roberto Raggi. (cherry picked from commit fca3ec1f3288ac4bcbfaed7f6c613af5cc762dda) --- src/plugins/cpptools/cppcodecompletion.cpp | 85 ++++++++++++++++------ src/plugins/cpptools/cppcodecompletion.h | 4 +- 2 files changed, 65 insertions(+), 24 deletions(-) diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 0ff66aaa6ee..20faa6e7a3c 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -432,7 +432,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) return -1; m_editor = editor; - m_startPosition = findStartOfName(editor); + m_startPosition = findStartOfName(); m_completionOperator = T_EOF_SYMBOL; int endOfOperator = m_startPosition; @@ -520,7 +520,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) if (m_completionOperator == T_LPAREN && completeFunction(exprTy, resolvedTypes, context)) { return m_startPosition; - } if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) && + } else if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) && completeMember(resolvedTypes, context)) { return m_startPosition; } else if (m_completionOperator == T_COLON_COLON && completeScope(resolvedTypes, context)) { @@ -531,6 +531,32 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) return m_startPosition; } } + + if (m_completionOperator == T_LPAREN) { + // Find the expression that precedes the current name + int index = endOfExpression; + while (m_editor->characterAt(index - 1).isSpace()) + --index; + index = findStartOfName(index); + + QTextCursor tc(edit->document()); + tc.setPosition(index); + QString baseExpression = expressionUnderCursor(tc); + + // Resolve the type of this expression + QList results = + typeOfExpression(baseExpression, thisDocument, symbol, TypeOfExpression::Preprocess); + + // If it's a class, add completions for the constructors + foreach (const TypeOfExpression::Result &result, results) { + if (result.first->isClass()) { + FullySpecifiedType exprTy = result.first; + if (completeConstructors(exprTy->asClass())) + return m_startPosition; + break; + } + } + } } // nothing to do. @@ -541,26 +567,14 @@ bool CppCodeCompletion::completeFunction(FullySpecifiedType exprTy, const QList &resolvedTypes, const LookupContext &) { - ConvertToCompletionItem toCompletionItem(this); - Overview o; - o.setShowReturnTypes(true); - o.setShowArgumentNames(true); - if (Class *klass = exprTy->asClass()) { - for (unsigned i = 0; i < klass->memberCount(); ++i) { - Symbol *member = klass->memberAt(i); - if (! member->type()->isFunction()) - continue; - else if (! member->identity()) - continue; - else if (! member->identity()->isEqualTo(klass->identity())) - continue; - if (TextEditor::CompletionItem item = toCompletionItem(member)) { - item.m_text = o(member->type(), member->name()); - m_completions.append(item); - } - } + completeConstructors(klass); } else { + ConvertToCompletionItem toCompletionItem(this); + Overview o; + o.setShowReturnTypes(true); + o.setShowArgumentNames(true); + QSet signatures; foreach (TypeOfExpression::Result p, resolvedTypes) { FullySpecifiedType ty = p.first; @@ -873,6 +887,30 @@ void CppCodeCompletion::completeClass(const QList &candidates, } } +bool CppCodeCompletion::completeConstructors(Class *klass) +{ + ConvertToCompletionItem toCompletionItem(this); + Overview o; + o.setShowReturnTypes(true); + o.setShowArgumentNames(true); + + for (unsigned i = 0; i < klass->memberCount(); ++i) { + Symbol *member = klass->memberAt(i); + if (! member->type()->isFunction()) + continue; + else if (! member->identity()) + continue; + else if (! member->identity()->isEqualTo(klass->identity())) + continue; + if (TextEditor::CompletionItem item = toCompletionItem(member)) { + item.m_text = o(member->type(), member->name()); + m_completions.append(item); + } + } + + return ! m_completions.isEmpty(); +} + bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType, const QList &results, const LookupContext &context, @@ -1150,14 +1188,15 @@ void CppCodeCompletion::cleanup() typeOfExpression.setSnapshot(Snapshot()); } -int CppCodeCompletion::findStartOfName(const TextEditor::ITextEditor *editor) +int CppCodeCompletion::findStartOfName(int pos) const { - int pos = editor->position(); + if (pos == -1) + pos = m_editor->position(); QChar chr; // Skip to the start of a name do { - chr = editor->characterAt(--pos); + chr = m_editor->characterAt(--pos); } while (chr.isLetterOrNumber() || chr == QLatin1Char('_')); return pos + 1; diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h index 08a767ea6ce..02bcdc0f524 100644 --- a/src/plugins/cpptools/cppcodecompletion.h +++ b/src/plugins/cpptools/cppcodecompletion.h @@ -103,6 +103,8 @@ private: const CPlusPlus::LookupContext &context, bool staticLookup = true); + bool completeConstructors(CPlusPlus::Class *klass); + bool completeQtMethod(CPlusPlus::FullySpecifiedType exprTy, const QList &, const CPlusPlus::LookupContext &context, @@ -118,7 +120,7 @@ private: const CPlusPlus::LookupContext &context) { return completeQtMethod(exprTy, results, context, false); } - static int findStartOfName(const TextEditor::ITextEditor *editor); + int findStartOfName(int pos = -1) const; QList m_completions; From 100a6254f69c6326d8bd6bd41b2b90eba6dfa0bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Mon, 16 Feb 2009 15:15:43 +0100 Subject: [PATCH 7/8] More intelligent function argument widget Now it shows immediately when there is only a single signature of a given method/constructor. (cherry picked from commit 8b9dd766c822a9f7b929ae14eab3e2e402307c8c) Conflicts: src/plugins/cpptools/cppcodecompletion.cpp --- src/plugins/cpptools/cppcodecompletion.cpp | 63 ++++++++++------------ src/plugins/cpptools/cppcodecompletion.h | 5 +- 2 files changed, 29 insertions(+), 39 deletions(-) diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 20faa6e7a3c..94258decc1a 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -518,7 +518,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) if (exprTy->isReferenceType()) exprTy = exprTy->asReferenceType()->elementType(); - if (m_completionOperator == T_LPAREN && completeFunction(exprTy, resolvedTypes, context)) { + if (m_completionOperator == T_LPAREN && completeConstructorOrFunction(exprTy, resolvedTypes)) { return m_startPosition; } else if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) && completeMember(resolvedTypes, context)) { @@ -551,7 +551,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) foreach (const TypeOfExpression::Result &result, results) { if (result.first->isClass()) { FullySpecifiedType exprTy = result.first; - if (completeConstructors(exprTy->asClass())) + if (completeConstructorOrFunction(exprTy, QList())) return m_startPosition; break; } @@ -563,18 +563,29 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) return -1; } -bool CppCodeCompletion::completeFunction(FullySpecifiedType exprTy, - const QList &resolvedTypes, - const LookupContext &) +bool CppCodeCompletion::completeConstructorOrFunction(FullySpecifiedType exprTy, + const QList &resolvedTypes) { - if (Class *klass = exprTy->asClass()) { - completeConstructors(klass); - } else { - ConvertToCompletionItem toCompletionItem(this); - Overview o; - o.setShowReturnTypes(true); - o.setShowArgumentNames(true); + ConvertToCompletionItem toCompletionItem(this); + Overview o; + o.setShowReturnTypes(true); + o.setShowArgumentNames(true); + if (Class *klass = exprTy->asClass()) { + for (unsigned i = 0; i < klass->memberCount(); ++i) { + Symbol *member = klass->memberAt(i); + if (! member->type()->isFunction()) + continue; + else if (! member->identity()) + continue; + else if (! member->identity()->isEqualTo(klass->identity())) + continue; + if (TextEditor::CompletionItem item = toCompletionItem(member)) { + item.m_text = o(member->type(), member->name()); + m_completions.append(item); + } + } + } else { QSet signatures; foreach (TypeOfExpression::Result p, resolvedTypes) { FullySpecifiedType ty = p.first; @@ -594,6 +605,10 @@ bool CppCodeCompletion::completeFunction(FullySpecifiedType exprTy, } } + // If there is only one item, show the function argument widget immediately + if (m_completions.size() == 1) + complete(m_completions.takeFirst()); + return ! m_completions.isEmpty(); } @@ -887,30 +902,6 @@ void CppCodeCompletion::completeClass(const QList &candidates, } } -bool CppCodeCompletion::completeConstructors(Class *klass) -{ - ConvertToCompletionItem toCompletionItem(this); - Overview o; - o.setShowReturnTypes(true); - o.setShowArgumentNames(true); - - for (unsigned i = 0; i < klass->memberCount(); ++i) { - Symbol *member = klass->memberAt(i); - if (! member->type()->isFunction()) - continue; - else if (! member->identity()) - continue; - else if (! member->identity()->isEqualTo(klass->identity())) - continue; - if (TextEditor::CompletionItem item = toCompletionItem(member)) { - item.m_text = o(member->type(), member->name()); - m_completions.append(item); - } - } - - return ! m_completions.isEmpty(); -} - bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType, const QList &results, const LookupContext &context, diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h index 02bcdc0f524..79f580236f9 100644 --- a/src/plugins/cpptools/cppcodecompletion.h +++ b/src/plugins/cpptools/cppcodecompletion.h @@ -86,9 +86,8 @@ private: void addMacros(const CPlusPlus::LookupContext &context); void addCompletionItem(CPlusPlus::Symbol *symbol); - bool completeFunction(CPlusPlus::FullySpecifiedType exprTy, - const QList &, - const CPlusPlus::LookupContext &context); + bool completeConstructorOrFunction(CPlusPlus::FullySpecifiedType exprTy, + const QList &); bool completeMember(const QList &, const CPlusPlus::LookupContext &context); From d94dd392cb3cbb0c39ec9eb5cce4deba4afc4c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Mon, 16 Feb 2009 18:34:56 +0100 Subject: [PATCH 8/8] Reuse the function argument widget when possible Now that we're showing this thing instantly, we can no longer rely on the thing hiding cause of a focus change. (cherry picked from commit 5a0a084c3130e0401eed687795371c2a49b4b635) Conflicts: src/plugins/cpptools/cppcodecompletion.cpp --- src/plugins/cpptools/cppcodecompletion.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 94258decc1a..b9dc55f0b99 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -187,10 +187,10 @@ using namespace CppTools::Internal; FunctionArgumentWidget::FunctionArgumentWidget() : m_item(0) { - QObject *editorObject = Core::ICore::instance()->editorManager()->currentEditor(); + QObject *editorObject = Core::EditorManager::instance()->currentEditor(); m_editor = qobject_cast(editorObject); - m_popupFrame = new QFrame(0, Qt::ToolTip|Qt::WindowStaysOnTopHint); + m_popupFrame = new QFrame(0, Qt::ToolTip | Qt::WindowStaysOnTopHint); m_popupFrame->setFocusPolicy(Qt::NoFocus); m_popupFrame->setAttribute(Qt::WA_DeleteOnClose); @@ -1069,7 +1069,10 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item) Function *function = symbol->type()->asFunction(); QTC_ASSERT(function, return); - m_functionArgumentWidget = new FunctionArgumentWidget(); + // Recreate if necessary + if (!m_functionArgumentWidget) + m_functionArgumentWidget = new FunctionArgumentWidget; + m_functionArgumentWidget->showFunctionHint(function, typeOfExpression.lookupContext()); } } else if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT) {