summaryrefslogtreecommitdiff
path: root/src/plugins/cpptools/cppcodecompletion.cpp
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@nokia.com>2010-06-18 12:34:32 +0200
committerErik Verbruggen <erik.verbruggen@nokia.com>2010-07-06 09:19:20 +0200
commit5d888caeb9f7b554827475227c3fc207b4f4b8da (patch)
tree1c2b4ba3591ec99d33ab225e9adab5ec2525b043 /src/plugins/cpptools/cppcodecompletion.cpp
parentc9710052bb3dbad93fdf5e030395f4d9f7f7fb7a (diff)
downloadqt-creator-5d888caeb9f7b554827475227c3fc207b4f4b8da.tar.gz
Added ObjC completion for message-send expressions.
Diffstat (limited to 'src/plugins/cpptools/cppcodecompletion.cpp')
-rw-r--r--src/plugins/cpptools/cppcodecompletion.cpp118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 03e6a9f28d..d6c23a700c 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -666,6 +666,119 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
return index;
}
+void CppCodeCompletion::completeObjCMsgSend(ClassOrNamespace *binding,
+ bool staticClassAccess)
+{
+ QList<Scope*> memberScopes;
+ foreach (Symbol *s, binding->symbols()) {
+ if (ObjCClass *c = s->asObjCClass())
+ memberScopes.append(c->members());
+ }
+
+ foreach (Scope *scope, memberScopes) {
+ for (unsigned i = 0; i < scope->symbolCount(); ++i) {
+ Symbol *symbol = scope->symbolAt(i);
+
+ if (ObjCMethod *method = symbol->type()->asObjCMethodType()) {
+ if (method->isStatic() == staticClassAccess) {
+ Overview oo;
+ const SelectorNameId *selectorName =
+ method->name()->asSelectorNameId();
+ QString text;
+ QString data;
+ if (selectorName->hasArguments()) {
+ for (unsigned i = 0; i < selectorName->nameCount(); ++i) {
+ if (i > 0)
+ text += QLatin1Char(' ');
+ Symbol *arg = method->argumentAt(i);
+ text += selectorName->nameAt(i)->identifier()->chars();
+ text += QLatin1Char(':');
+ text += QChar::ObjectReplacementCharacter;
+ text += QLatin1Char('(');
+ text += oo(arg->type());
+ text += QLatin1Char(')');
+ text += oo(arg->name());
+ text += QChar::ObjectReplacementCharacter;
+ }
+ } else {
+ text = selectorName->identifier()->chars();
+ }
+ data = text;
+
+ if (!text.isEmpty()) {
+ TextEditor::CompletionItem item(this);
+ item.text = text;
+ item.data = QVariant::fromValue(data);
+ m_completions.append(item);
+ }
+ }
+ }
+ }
+ }
+}
+
+bool CppCodeCompletion::tryObjCCompletion(TextEditor::BaseTextEditor *edit)
+{
+ Q_ASSERT(edit);
+
+ int end = m_editor->position();
+ while (m_editor->characterAt(end).isSpace())
+ ++end;
+ if (m_editor->characterAt(end) != QLatin1Char(']'))
+ return false;
+
+ QTextCursor tc(edit->document());
+ tc.setPosition(end);
+ BackwardsScanner tokens(tc);
+ if (tokens[tokens.startToken() - 1].isNot(T_RBRACKET))
+ return false;
+
+ const int start = tokens.startOfMatchingBrace(tokens.startToken());
+ if (start == tokens.startToken())
+ return false;
+
+ const int startPos = tokens[start].begin() + tokens.startPosition();
+ const QString expr = m_editor->textAt(startPos, m_editor->position() - startPos);
+
+ const Snapshot snapshot = m_manager->snapshot();
+ Document::Ptr thisDocument = snapshot.document(m_editor->file()->fileName());
+ if (! thisDocument)
+ return false;
+
+ typeOfExpression.init(thisDocument, snapshot);
+ int line = 0, column = 0;
+ edit->convertPosition(m_editor->position(), &line, &column);
+ Scope *scope = thisDocument->scopeAt(line, column);
+ if (!scope)
+ return false;
+
+ const QList<LookupItem> items = typeOfExpression(expr, scope);
+ LookupContext lookupContext(thisDocument, snapshot);
+
+ foreach (const LookupItem &item, items) {
+ FullySpecifiedType ty = item.type().simplified();
+ if (ty->isPointerType()) {
+ ty = ty->asPointerType()->elementType().simplified();
+
+ if (NamedType *namedTy = ty->asNamedType()) {
+ ClassOrNamespace *binding = lookupContext.lookupType(namedTy->name(), item.scope());
+ completeObjCMsgSend(binding, false);
+ }
+ } else {
+ if (ObjCClass *clazz = ty->asObjCClassType()) {
+ ClassOrNamespace *binding = lookupContext.lookupType(clazz->name(), item.scope());
+ completeObjCMsgSend(binding, true);
+ }
+ }
+ }
+
+ if (m_completions.isEmpty())
+ return false;
+
+ m_startPosition = m_editor->position();
+ return true;
+}
+
int CppCodeCompletion::startCompletionHelper(TextEditor::ITextEditable *editor)
{
TextEditor::BaseTextEditor *edit = qobject_cast<TextEditor::BaseTextEditor *>(editor->widget());
@@ -674,6 +787,11 @@ int CppCodeCompletion::startCompletionHelper(TextEditor::ITextEditable *editor)
m_editor = editor;
+ if (m_objcEnabled) {
+ if (tryObjCCompletion(edit))
+ return m_startPosition;
+ }
+
const int startOfName = findStartOfName();
m_startPosition = startOfName;
m_completionOperator = T_EOF_SYMBOL;