diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index a68a4cd127c778474197865d43658732e0ecb267..09166ef0528b0a39900b4ca6ab83062f2386da5b 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -767,11 +767,18 @@ int CppCodeCompletion::startCompletionInternal(TextEditor::BaseTextEditor *edit, return -1; typeOfExpression.init(thisDocument, snapshot); - Symbol *lastVisibleSymbol = thisDocument->lastVisibleSymbolAt(line, column); + + Scope *scope = thisDocument->scopeAt(line, column); + Q_ASSERT(scope != 0); if (expression.isEmpty()) { - if (m_completionOperator == T_EOF_SYMBOL || m_completionOperator == T_COLON_COLON) - return globalCompletion(lastVisibleSymbol, thisDocument, snapshot); + if (m_completionOperator == T_EOF_SYMBOL || m_completionOperator == T_COLON_COLON) { + (void) typeOfExpression(expression, scope); + globalCompletion(scope); + if (m_completions.isEmpty()) + return -1; + return m_startPosition; + } else if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT) { // Apply signal/slot completion on 'this' @@ -779,9 +786,6 @@ int CppCodeCompletion::startCompletionInternal(TextEditor::BaseTextEditor *edit, } } - Scope *scope = thisDocument->scopeAt(line, column); - Q_ASSERT(scope != 0); - if (debug) qDebug() << "scope:" << scope->owner()->fileName() << scope->owner()->line() << scope->owner()->column(); @@ -871,26 +875,69 @@ int CppCodeCompletion::startCompletionInternal(TextEditor::BaseTextEditor *edit, return -1; } -int CppCodeCompletion::globalCompletion(Symbol *lastVisibleSymbol, - Document::Ptr thisDocument, - const Snapshot &snapshot) +void CppCodeCompletion::globalCompletion(Scope *currentScope) { - if (m_completionOperator == T_EOF_SYMBOL) { - addKeywords(); - addMacros(thisDocument->fileName(), snapshot); + const LookupContext &context = typeOfExpression.context(); + + if (m_completionOperator == T_COLON_COLON) { + completeNamespace(context.globalNamespace()); + return; } - Document::Ptr exprDoc = Document::create(QLatin1String("<expression>")); - const DeprecatedLookupContext context(lastVisibleSymbol, exprDoc, thisDocument, snapshot); - const QList<Scope *> scopes = context.expand(context.visibleScopes()); + addKeywords(); + addMacros(context.thisDocument()->fileName(), context.snapshot()); + + QList<ClassOrNamespace *> usingBindings; + ClassOrNamespace *currentBinding = 0; - foreach (Scope *scope, scopes) { - for (unsigned i = 0; i < scope->symbolCount(); ++i) { - addCompletionItem(scope->symbolAt(i)); + for (Scope *scope = currentScope; scope; scope = scope->enclosingScope()) { + if (scope->isBlockScope()) { + if (ClassOrNamespace *binding = context.lookupType(scope->owner())) { + for (unsigned i = 0; i < scope->symbolCount(); ++i) { + Symbol *member = scope->symbolAt(i); + if (! member->name()) + continue; + else if (UsingNamespaceDirective *u = member->asUsingNamespaceDirective()) { + if (ClassOrNamespace *b = binding->lookupType(u->name())) + usingBindings.append(b); + } + } + } + } else if (scope->isFunctionScope() || scope->isClassScope() || scope->isNamespaceScope()) { + currentBinding = context.lookupType(scope->owner()); + break; + } + } + + for (; currentBinding; currentBinding = currentBinding->parent()) { + const QList<Symbol *> symbols = currentBinding->symbols(); + + if (! symbols.isEmpty()) { + if (symbols.first()->isNamespace()) + completeNamespace(currentBinding); + else + completeClass(currentBinding, false); } } - return m_startPosition; + foreach (ClassOrNamespace *b, usingBindings) + completeNamespace(b); + + for (Scope *scope = currentScope; scope; scope = scope->enclosingScope()) { + if (scope->isBlockScope()) { + for (unsigned i = 0; i < scope->symbolCount(); ++i) { + addCompletionItem(scope->symbolAt(i)); + } + } else if (scope->isFunctionScope()) { + Scope *arguments = scope->owner()->asFunction()->arguments(); + for (unsigned i = 0; i < arguments->symbolCount(); ++i) { + addCompletionItem(arguments->symbolAt(i)); + } + break; + } else { + break; + } + } } bool CppCodeCompletion::completeConstructorOrFunction(const QList<LookupItem> &results, @@ -1508,6 +1555,9 @@ bool CppCodeCompletion::completeQtMethod(const QList<LookupItem> &results, void CppCodeCompletion::completions(QList<TextEditor::CompletionItem> *completions) { const int length = m_editor->position() - m_startPosition; + if (length < 0) + return; + const QString key = m_editor->textAt(m_startPosition, length); if (length == 0) diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h index edc76104bf0ac96a4b904b4d7b13bd0262fc3bbd..39d23adf68bf6d2b4278becbf7cd6044b1fa5bf0 100644 --- a/src/plugins/cpptools/cppcodecompletion.h +++ b/src/plugins/cpptools/cppcodecompletion.h @@ -96,9 +96,7 @@ private: bool completeInclude(const QTextCursor &cursor); void completePreprocessor(); - int globalCompletion(CPlusPlus::Symbol *lastVisibleSymbol, - CPlusPlus::Document::Ptr thisDocument, - const CPlusPlus::Snapshot &snapshot); + void globalCompletion(CPlusPlus::Scope *scope); bool completeConstructorOrFunction(const QList<CPlusPlus::LookupItem> &results, int endOfExpression, bool toolTipOnly);