Commit 8dc369bc authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Simplified member completion.

Share code with ResolveExpression.
parent 99172852
......@@ -647,7 +647,8 @@ bool ResolveExpression::visit(MemberAccessAST *ast)
}
QList<ResolveExpression::Result>
ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int accessOp) const
ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int accessOp,
bool *replacedDotOperator) const
{
QList<Result> results;
......@@ -715,6 +716,16 @@ ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int a
results.append(Result(elementTy, lastVisibleSymbol));
}
} else if (accessOp == T_DOT) {
if (replacedDotOperator) {
if (PointerType *ptrTy = ty->asPointerType()) {
*replacedDotOperator = true;
ty = ptrTy->elementType().simplified();
} else if (ArrayType *arrTy = ty->asArrayType()) {
*replacedDotOperator = true;
ty = arrTy->elementType().simplified();
}
}
if (ty->isClassType() || ty->isNamedType())
results.append(Result(ty, lastVisibleSymbol));
......@@ -734,12 +745,13 @@ ResolveExpression::resolveBaseExpression(const QList<Result> &baseResults, int a
QList<ResolveExpression::Result>
ResolveExpression::resolveMemberExpression(const QList<Result> &baseResults,
unsigned accessOp,
Name *memberName) const
Name *memberName,
bool *replacedDotOperator) const
{
ResolveClass resolveClass;
QList<Result> results;
const QList<Result> classObjectResults = resolveBaseExpression(baseResults, accessOp);
const QList<Result> classObjectResults = resolveBaseExpression(baseResults, accessOp, replacedDotOperator);
foreach (const Result &r, classObjectResults) {
FullySpecifiedType ty = r.first;
......
......@@ -51,7 +51,8 @@ public:
QList<Result> resolveMemberExpression(const QList<Result> &baseResults,
unsigned accessOp,
Name *memberName) const;
Name *memberName,
bool *replacedDotOperator = 0) const;
QList<Result> resolveMember(Name *memberName, Class *klass, Name *className = 0) const;
......@@ -65,7 +66,8 @@ public:
QList<Result> resolveBaseExpression(const QList<Result> &baseResults,
int accessOp) const;
int accessOp,
bool *replacedDotOperator = 0) const;
protected:
QList<Result> switchResults(const QList<Result> &symbols);
......
......@@ -984,135 +984,42 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
return false;
}
bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &results,
bool CppCodeCompletion::completeMember(const QList<TypeOfExpression::Result> &baseResults,
const LookupContext &context)
{
if (results.isEmpty())
if (baseResults.isEmpty())
return false;
TypeOfExpression::Result result = results.first();
QList<Symbol *> classObjectCandidates;
if (m_completionOperator == T_ARROW) {
FullySpecifiedType ty = result.first.simplified();
if (Class *classTy = ty->asClassType()) {
Symbol *symbol = result.second;
if (symbol && ! symbol->isClass())
classObjectCandidates.append(classTy);
} else if (NamedType *namedTy = ty->asNamedType()) {
// ### This code is pretty slow.
const QList<Symbol *> candidates = context.resolve(namedTy->name());
foreach (Symbol *candidate, candidates) {
if (candidate->isTypedef()) {
ty = candidate->type();
const ResolveExpression::Result r(ty, candidate);
result = r;
break;
}
}
}
if (NamedType *namedTy = ty->asNamedType()) {
ResolveExpression resolveExpression(context);
ResolveClass resolveClass;
const QList<Symbol *> candidates = resolveClass(namedTy->name(), result, context);
foreach (Symbol *classObject, candidates) {
const QList<TypeOfExpression::Result> overloads =
resolveExpression.resolveArrowOperator(result, namedTy,
classObject->asClass());
foreach (TypeOfExpression::Result r, overloads) {
FullySpecifiedType ty = r.first;
Function *funTy = ty->asFunctionType();
if (! funTy)
continue;
ty = funTy->returnType().simplified();
if (PointerType *ptrTy = ty->asPointerType()) {
FullySpecifiedType elementTy = ptrTy->elementType().simplified();
if (NamedType *namedTy = elementTy->asNamedType()) {
const QList<Symbol *> classes =
resolveClass(namedTy->name(), result, context);
foreach (Symbol *c, classes) {
if (! classObjectCandidates.contains(c))
classObjectCandidates.append(c);
}
}
}
}
}
} else if (PointerType *ptrTy = ty->asPointerType()) {
FullySpecifiedType elementTy = ptrTy->elementType().simplified();
if (NamedType *namedTy = elementTy->asNamedType()) {
ResolveClass resolveClass;
const QList<Symbol *> classes = resolveClass(namedTy->name(), result,
context);
foreach (Symbol *c, classes) {
if (! classObjectCandidates.contains(c))
classObjectCandidates.append(c);
}
} else if (Class *classTy = elementTy->asClassType()) {
// typedef struct { int x } *Ptr;
// Ptr p;
// p->
classObjectCandidates.append(classTy);
}
}
} else if (m_completionOperator == T_DOT) {
FullySpecifiedType ty = result.first.simplified();
NamedType *namedTy = 0;
ResolveExpression resolveExpression(context);
ResolveClass resolveClass;
if (ArrayType *arrayTy = ty->asArrayType()) {
// Replace . with [0]. when `ty' is an array type.
FullySpecifiedType elementTy = arrayTy->elementType().simplified();
bool replacedDotOperator = false;
const QList<TypeOfExpression::Result> classObjectResults =
resolveExpression.resolveBaseExpression(baseResults,
m_completionOperator,
&replacedDotOperator);
if (replacedDotOperator) {
// Replace . with ->
int length = m_editor->position() - m_startPosition + 1;
m_editor->setCurPos(m_startPosition - 1);
m_editor->replace(length, QLatin1String("->"));
++m_startPosition;
}
if (elementTy->isNamedType() || elementTy->isPointerType()) {
ty = elementTy;
QList<Symbol *> classObjectCandidates;
foreach (const TypeOfExpression::Result &r, classObjectResults) {
FullySpecifiedType ty = r.first.simplified();
const int length = m_editor->position() - m_startPosition + 1;
m_editor->setCurPos(m_startPosition - 1);
m_editor->replace(length, QLatin1String("[0]."));
m_startPosition += 3;
}
}
if (Class *klass = ty->asClassType())
classObjectCandidates.append(klass);
if (PointerType *ptrTy = ty->asPointerType()) {
if (ptrTy->elementType()->isNamedType()) {
// Replace . with ->
int length = m_editor->position() - m_startPosition + 1;
m_editor->setCurPos(m_startPosition - 1);
m_editor->replace(length, QLatin1String("->"));
++m_startPosition;
namedTy = ptrTy->elementType()->asNamedType();
}
} else if (Class *classTy = ty->asClassType()) {
Symbol *symbol = result.second;
if (symbol && ! symbol->isClass())
classObjectCandidates.append(classTy);
} else {
namedTy = ty->asNamedType();
if (! namedTy) {
Function *fun = ty->asFunctionType();
if (fun && fun->scope() && (fun->scope()->isBlockScope() || fun->scope()->isNamespaceScope()))
namedTy = fun->returnType()->asNamedType();
}
}
else if (NamedType *namedTy = ty->asNamedType()) {
Name *className = namedTy->name();
const QList<Symbol *> classes = resolveClass(className, r, context);
if (namedTy) {
ResolveClass resolveClass;
const QList<Symbol *> symbols = resolveClass(namedTy->name(), result,
context);
foreach (Symbol *symbol, symbols) {
if (classObjectCandidates.contains(symbol))
continue;
if (Class *klass = symbol->asClass())
foreach (Symbol *c, classes) {
if (Class *klass = c->asClass())
classObjectCandidates.append(klass);
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment