forked from qt-creator/qt-creator
Simplified member completion.
Share code with ResolveExpression.
This commit is contained in:
@@ -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();
|
||||
ResolveExpression resolveExpression(context);
|
||||
ResolveClass resolveClass;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
QList<Symbol *> classObjectCandidates;
|
||||
foreach (const TypeOfExpression::Result &r, classObjectResults) {
|
||||
FullySpecifiedType ty = r.first.simplified();
|
||||
|
||||
if (m_completionOperator == T_ARROW) {
|
||||
FullySpecifiedType ty = result.first.simplified();
|
||||
if (Class *klass = ty->asClassType())
|
||||
classObjectCandidates.append(klass);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (NamedType *namedTy = ty->asNamedType()) {
|
||||
Name *className = namedTy->name();
|
||||
const QList<Symbol *> classes = resolveClass(className, r, context);
|
||||
|
||||
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;
|
||||
|
||||
if (ArrayType *arrayTy = ty->asArrayType()) {
|
||||
// Replace . with [0]. when `ty' is an array type.
|
||||
FullySpecifiedType elementTy = arrayTy->elementType().simplified();
|
||||
|
||||
if (elementTy->isNamedType() || elementTy->isPointerType()) {
|
||||
ty = elementTy;
|
||||
|
||||
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 (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();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user