forked from qt-creator/qt-creator
Introduced helpers to rewrite types and names.
Done-with: Erik Verbruggen
This commit is contained in:
@@ -740,11 +740,12 @@ Symbol *Snapshot::findMatchingDefinition(Symbol *declaration) const
|
||||
continue; // nothing to do
|
||||
|
||||
foreach (Function *fun, result) {
|
||||
const QList<Symbol *> declarations = context.lookup(fun->name(), fun->scope());
|
||||
const QList<LookupItem> declarations = context.lookup(fun->name(), fun->scope());
|
||||
if (declarations.isEmpty())
|
||||
continue;
|
||||
|
||||
else if (enclosingType == context.lookupType(declarations.first()))
|
||||
const LookupItem best = declarations.first();
|
||||
if (enclosingType == context.lookupType(best.declaration()))
|
||||
viableFunctions.append(fun);
|
||||
}
|
||||
|
||||
|
||||
364
src/libs/cplusplus/CppRewriter.cpp
Normal file
364
src/libs/cplusplus/CppRewriter.cpp
Normal file
@@ -0,0 +1,364 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://qt.nokia.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
#include "CppRewriter.h"
|
||||
#include <TypeVisitor.h>
|
||||
#include <NameVisitor.h>
|
||||
#include <CoreTypes.h>
|
||||
#include <Symbols.h>
|
||||
#include <Literals.h>
|
||||
#include <Names.h>
|
||||
#include <Scope.h>
|
||||
|
||||
#include <QtCore/QVarLengthArray>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
using namespace CPlusPlus;
|
||||
|
||||
class CPlusPlus::Rewrite
|
||||
{
|
||||
public:
|
||||
Rewrite(Control *control, const SubstitutionEnvironment &env)
|
||||
: control(control), env(env), rewriteType(this), rewriteName(this) {}
|
||||
|
||||
class RewriteType: public TypeVisitor
|
||||
{
|
||||
Rewrite *rewrite;
|
||||
QList<FullySpecifiedType> temps;
|
||||
|
||||
Control *control() const
|
||||
{ return rewrite->control; }
|
||||
|
||||
void accept(const FullySpecifiedType &ty)
|
||||
{
|
||||
TypeVisitor::accept(ty.type());
|
||||
unsigned flags = ty.flags();
|
||||
flags |= temps.back().flags();
|
||||
temps.back().setFlags(flags);
|
||||
}
|
||||
|
||||
public:
|
||||
RewriteType(Rewrite *r): rewrite(r) {}
|
||||
|
||||
FullySpecifiedType operator()(const FullySpecifiedType &ty)
|
||||
{
|
||||
accept(ty);
|
||||
return temps.takeLast();
|
||||
}
|
||||
|
||||
virtual void visit(UndefinedType *)
|
||||
{
|
||||
temps.append(FullySpecifiedType());
|
||||
}
|
||||
|
||||
virtual void visit(VoidType *)
|
||||
{
|
||||
temps.append(control()->voidType());
|
||||
}
|
||||
|
||||
virtual void visit(IntegerType *type)
|
||||
{
|
||||
temps.append(control()->integerType(type->kind()));
|
||||
}
|
||||
|
||||
virtual void visit(FloatType *type)
|
||||
{
|
||||
temps.append(control()->floatType(type->kind()));
|
||||
}
|
||||
|
||||
virtual void visit(PointerToMemberType *type)
|
||||
{
|
||||
const Name *memberName = rewrite->rewriteName(type->memberName());
|
||||
const FullySpecifiedType elementType = rewrite->rewriteType(type->elementType());
|
||||
temps.append(control()->pointerToMemberType(memberName, elementType));
|
||||
}
|
||||
|
||||
virtual void visit(PointerType *type)
|
||||
{
|
||||
const FullySpecifiedType elementType = rewrite->rewriteType(type->elementType());
|
||||
temps.append(control()->pointerType(elementType));
|
||||
}
|
||||
|
||||
virtual void visit(ReferenceType *type)
|
||||
{
|
||||
const FullySpecifiedType elementType = rewrite->rewriteType(type->elementType());
|
||||
temps.append(control()->referenceType(elementType));
|
||||
}
|
||||
|
||||
virtual void visit(ArrayType *type)
|
||||
{
|
||||
const FullySpecifiedType elementType = rewrite->rewriteType(type->elementType());
|
||||
temps.append(control()->arrayType(elementType, type->size()));
|
||||
}
|
||||
|
||||
virtual void visit(NamedType *type)
|
||||
{
|
||||
FullySpecifiedType ty = rewrite->env.apply(type->name(), rewrite);
|
||||
if (! ty->isUndefinedType())
|
||||
temps.append(rewrite->rewriteType(ty));
|
||||
else {
|
||||
const Name *name = rewrite->rewriteName(type->name());
|
||||
temps.append(control()->namedType(name));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(Function *type)
|
||||
{
|
||||
Function *funTy = control()->newFunction(0, 0);
|
||||
funTy->copy(type);
|
||||
|
||||
funTy->setName(rewrite->rewriteName(type->name()));
|
||||
|
||||
funTy->setReturnType(rewrite->rewriteType(type->returnType()));
|
||||
|
||||
for (unsigned i = 0; i < type->argumentCount(); ++i) {
|
||||
Symbol *arg = type->argumentAt(i);
|
||||
|
||||
Argument *newArg = control()->newArgument(0, 0);
|
||||
newArg->copy(arg);
|
||||
newArg->setName(rewrite->rewriteName(arg->name()));
|
||||
newArg->setType(rewrite->rewriteType(arg->type()));
|
||||
|
||||
funTy->arguments()->enterSymbol(newArg);
|
||||
}
|
||||
|
||||
temps.append(funTy);
|
||||
}
|
||||
|
||||
virtual void visit(Namespace *type)
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO;
|
||||
temps.append(type);
|
||||
}
|
||||
|
||||
virtual void visit(Class *type)
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO;
|
||||
temps.append(type);
|
||||
}
|
||||
|
||||
virtual void visit(Enum *type)
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO;
|
||||
temps.append(type);
|
||||
}
|
||||
|
||||
virtual void visit(ForwardClassDeclaration *type)
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO;
|
||||
temps.append(type);
|
||||
}
|
||||
|
||||
virtual void visit(ObjCClass *type)
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO;
|
||||
temps.append(type);
|
||||
}
|
||||
|
||||
virtual void visit(ObjCProtocol *type)
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO;
|
||||
temps.append(type);
|
||||
}
|
||||
|
||||
virtual void visit(ObjCMethod *type)
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO;
|
||||
temps.append(type);
|
||||
}
|
||||
|
||||
virtual void visit(ObjCForwardClassDeclaration *type)
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO;
|
||||
temps.append(type);
|
||||
}
|
||||
|
||||
virtual void visit(ObjCForwardProtocolDeclaration *type)
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO;
|
||||
temps.append(type);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class RewriteName: public NameVisitor
|
||||
{
|
||||
Rewrite *rewrite;
|
||||
QList<const Name *> temps;
|
||||
|
||||
Control *control() const
|
||||
{ return rewrite->control; }
|
||||
|
||||
const Identifier *identifier(const Identifier *other) const
|
||||
{
|
||||
if (! other)
|
||||
return 0;
|
||||
|
||||
return control()->findOrInsertIdentifier(other->chars(), other->size());
|
||||
}
|
||||
|
||||
public:
|
||||
RewriteName(Rewrite *r): rewrite(r) {}
|
||||
|
||||
const Name *operator()(const Name *name)
|
||||
{
|
||||
if (! name)
|
||||
return 0;
|
||||
|
||||
accept(name);
|
||||
return temps.takeLast();
|
||||
}
|
||||
|
||||
virtual void visit(const QualifiedNameId *name)
|
||||
{
|
||||
const Name *base = rewrite->rewriteName(name->base());
|
||||
const Name *n = rewrite->rewriteName(name->name());
|
||||
temps.append(control()->qualifiedNameId(base, n));
|
||||
}
|
||||
|
||||
virtual void visit(const NameId *name)
|
||||
{
|
||||
temps.append(control()->nameId(identifier(name->identifier())));
|
||||
}
|
||||
|
||||
virtual void visit(const TemplateNameId *name)
|
||||
{
|
||||
QVarLengthArray<FullySpecifiedType, 8> args(name->templateArgumentCount());
|
||||
for (unsigned i = 0; i < name->templateArgumentCount(); ++i)
|
||||
args[i] = rewrite->rewriteType(name->templateArgumentAt(i));
|
||||
temps.append(control()->templateNameId(identifier(name->identifier()), args.data(), args.size()));
|
||||
}
|
||||
|
||||
virtual void visit(const DestructorNameId *name)
|
||||
{
|
||||
temps.append(control()->destructorNameId(identifier(name->identifier())));
|
||||
}
|
||||
|
||||
virtual void visit(const OperatorNameId *name)
|
||||
{
|
||||
temps.append(control()->operatorNameId(name->kind()));
|
||||
}
|
||||
|
||||
virtual void visit(const ConversionNameId *name)
|
||||
{
|
||||
FullySpecifiedType ty = rewrite->rewriteType(name->type());
|
||||
temps.append(control()->conversionNameId(ty));
|
||||
}
|
||||
|
||||
virtual void visit(const SelectorNameId *name)
|
||||
{
|
||||
QVarLengthArray<const Name *, 8> names(name->nameCount());
|
||||
for (unsigned i = 0; i < name->nameCount(); ++i)
|
||||
names[i] = rewrite->rewriteName(name->nameAt(i));
|
||||
temps.append(control()->selectorNameId(names.constData(), names.size(), name->hasArguments()));
|
||||
}
|
||||
};
|
||||
|
||||
public: // attributes
|
||||
Control *control;
|
||||
SubstitutionEnvironment env;
|
||||
RewriteType rewriteType;
|
||||
RewriteName rewriteName;
|
||||
};
|
||||
|
||||
ContextSubstitution::ContextSubstitution(const LookupContext &context, Scope *scope)
|
||||
: _context(context), _scope(scope)
|
||||
{
|
||||
}
|
||||
|
||||
ContextSubstitution::~ContextSubstitution()
|
||||
{
|
||||
}
|
||||
|
||||
FullySpecifiedType ContextSubstitution::apply(const Name *name, Rewrite *rewrite) const
|
||||
{
|
||||
const QList<LookupItem> candidates = _context.lookup(name, _scope);
|
||||
|
||||
foreach (const LookupItem &r, candidates) {
|
||||
Symbol *s = r.declaration();
|
||||
if (s->isDeclaration() && s->isTypedef()) {
|
||||
qDebug() << "resolved typedef:" << s->fileName() << s->line() << s->column();
|
||||
|
||||
qDebug() << "scope is:" << r.scope()->owner()->fileName()
|
||||
<< r.scope()->owner()->line()
|
||||
<< r.scope()->owner()->column();
|
||||
|
||||
ContextSubstitution subst(_context, s->scope());
|
||||
rewrite->env.enter(&subst);
|
||||
FullySpecifiedType ty = rewrite->rewriteType(s->type());
|
||||
rewrite->env.leave();
|
||||
|
||||
return ty;
|
||||
}
|
||||
}
|
||||
return FullySpecifiedType();
|
||||
}
|
||||
|
||||
|
||||
SubstitutionMap::SubstitutionMap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SubstitutionMap::~SubstitutionMap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SubstitutionMap::bind(const Name *name, const FullySpecifiedType &ty)
|
||||
{
|
||||
_map.append(qMakePair(name, ty));
|
||||
}
|
||||
|
||||
FullySpecifiedType SubstitutionMap::apply(const Name *name, Rewrite *) const
|
||||
{
|
||||
for (int n = _map.size() - 1; n != -1; --n) {
|
||||
const QPair<const Name *, FullySpecifiedType> &p = _map.at(n);
|
||||
|
||||
if (name->isEqualTo(p.first))
|
||||
return p.second;
|
||||
}
|
||||
|
||||
return FullySpecifiedType();
|
||||
}
|
||||
|
||||
FullySpecifiedType CPlusPlus::rewriteType(const FullySpecifiedType &type,
|
||||
const SubstitutionEnvironment &env,
|
||||
Control *control)
|
||||
{
|
||||
Rewrite rewrite(control, env);
|
||||
return rewrite.rewriteType(type);
|
||||
}
|
||||
|
||||
const Name *CPlusPlus::rewriteName(const Name *name,
|
||||
const SubstitutionEnvironment &env,
|
||||
Control *control)
|
||||
{
|
||||
Rewrite rewrite(control, env);
|
||||
return rewrite.rewriteName(name);
|
||||
}
|
||||
119
src/libs/cplusplus/CppRewriter.h
Normal file
119
src/libs/cplusplus/CppRewriter.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://qt.nokia.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CPLUSPLUS_REWRITER_H
|
||||
#define CPLUSPLUS_REWRITER_H
|
||||
|
||||
#include "CppDocument.h"
|
||||
#include "LookupContext.h"
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class Rewrite;
|
||||
|
||||
class CPLUSPLUS_EXPORT Substitution
|
||||
{
|
||||
Q_DISABLE_COPY(Substitution)
|
||||
|
||||
public:
|
||||
Substitution() {}
|
||||
virtual ~Substitution() {}
|
||||
|
||||
virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const = 0;
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT SubstitutionEnvironment
|
||||
{
|
||||
QList<Substitution *> substs;
|
||||
|
||||
public:
|
||||
FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const
|
||||
{
|
||||
if (name) {
|
||||
for (int index = substs.size() - 1; index != -1; --index) {
|
||||
const Substitution *subst = substs.at(index);
|
||||
|
||||
FullySpecifiedType ty = subst->apply(name, rewrite);
|
||||
if (! ty->isUndefinedType())
|
||||
return ty;
|
||||
}
|
||||
}
|
||||
|
||||
return FullySpecifiedType();
|
||||
}
|
||||
|
||||
void enter(Substitution *subst)
|
||||
{
|
||||
substs.append(subst);
|
||||
}
|
||||
|
||||
void leave()
|
||||
{
|
||||
substs.removeLast();
|
||||
}
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT ContextSubstitution: public Substitution
|
||||
{
|
||||
public:
|
||||
ContextSubstitution(const LookupContext &context, Scope *scope);
|
||||
virtual ~ContextSubstitution();
|
||||
|
||||
virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const;
|
||||
|
||||
private:
|
||||
LookupContext _context;
|
||||
Scope *_scope;
|
||||
};
|
||||
|
||||
|
||||
class CPLUSPLUS_EXPORT SubstitutionMap: public Substitution
|
||||
{
|
||||
public:
|
||||
SubstitutionMap();
|
||||
virtual ~SubstitutionMap();
|
||||
|
||||
void bind(const Name *name, const FullySpecifiedType &ty);
|
||||
virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const;
|
||||
|
||||
private:
|
||||
QList<QPair<const Name *, FullySpecifiedType> > _map;
|
||||
};
|
||||
|
||||
CPLUSPLUS_EXPORT FullySpecifiedType rewriteType(const FullySpecifiedType &type,
|
||||
const SubstitutionEnvironment &env,
|
||||
Control *control);
|
||||
|
||||
CPLUSPLUS_EXPORT const Name *rewriteName(const Name *name,
|
||||
const SubstitutionEnvironment &env,
|
||||
Control *control);
|
||||
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
#endif
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
typedef QList< QPair<const Identifier *, FullySpecifiedType> > Substitution;
|
||||
|
||||
public:
|
||||
static FullySpecifiedType instantiate(const Name *className, Symbol *candidate, QSharedPointer<Control> control);
|
||||
Q_DECL_DEPRECATED static FullySpecifiedType instantiate(const Name *className, Symbol *candidate, QSharedPointer<Control> control);
|
||||
|
||||
private:
|
||||
DeprecatedGenTemplateInstance(QSharedPointer<Control> control, const Substitution &substitution);
|
||||
|
||||
@@ -124,7 +124,7 @@ Scope *FindUsages::scopeAt(unsigned tokenIndex) const
|
||||
return _doc->scopeAt(line, column);
|
||||
}
|
||||
|
||||
void FindUsages::reportResult(unsigned tokenIndex, const QList<Symbol *> &candidates)
|
||||
void FindUsages::reportResult(unsigned tokenIndex, const QList<LookupItem> &candidates)
|
||||
{
|
||||
if (_processed.contains(tokenIndex))
|
||||
return;
|
||||
@@ -160,11 +160,12 @@ void FindUsages::reportResult(unsigned tokenIndex)
|
||||
_references.append(tokenIndex);
|
||||
}
|
||||
|
||||
bool FindUsages::checkCandidates(const QList<Symbol *> &candidates) const
|
||||
bool FindUsages::checkCandidates(const QList<LookupItem> &candidates) const
|
||||
{
|
||||
if (ClassOrNamespace *c = _context.lookupType(_declSymbol)) {
|
||||
for (int i = candidates.size() - 1; i != -1; --i) {
|
||||
Symbol *s = candidates.at(i);
|
||||
const LookupItem &r = candidates.at(i);
|
||||
Symbol *s = r.declaration();
|
||||
if (_context.lookupType(s) == c)
|
||||
return true;
|
||||
}
|
||||
@@ -186,7 +187,7 @@ bool FindUsages::visit(MemInitializerAST *ast)
|
||||
|
||||
SimpleNameAST *simple = ast->name->asSimpleName();
|
||||
if (identifier(simple->identifier_token) == _id) {
|
||||
const QList<Symbol *> candidates = _context.lookup(simple->name, scopeAt(simple->identifier_token));
|
||||
const QList<LookupItem> candidates = _context.lookup(simple->name, scopeAt(simple->identifier_token));
|
||||
reportResult(simple->identifier_token, candidates);
|
||||
}
|
||||
}
|
||||
@@ -223,14 +224,7 @@ void FindUsages::checkExpression(unsigned startToken, unsigned endToken)
|
||||
const QList<LookupItem> results = typeofExpression(expression, scope,
|
||||
TypeOfExpression::Preprocess);
|
||||
|
||||
QList<Symbol *> candidates;
|
||||
|
||||
foreach (const LookupItem &r, results) {
|
||||
Symbol *lastVisibleSymbol = r.declaration();
|
||||
candidates.append(lastVisibleSymbol);
|
||||
}
|
||||
|
||||
reportResult(endToken, candidates);
|
||||
reportResult(endToken, results);
|
||||
}
|
||||
|
||||
bool FindUsages::visit(QualifiedNameAST *ast)
|
||||
@@ -297,7 +291,7 @@ bool FindUsages::visit(EnumeratorAST *ast)
|
||||
{
|
||||
const Identifier *id = identifier(ast->identifier_token);
|
||||
if (id == _id) {
|
||||
const QList<Symbol *> candidates = _context.lookup(control()->nameId(id), scopeAt(ast->identifier_token));
|
||||
const QList<LookupItem> candidates = _context.lookup(control()->nameId(id), scopeAt(ast->identifier_token));
|
||||
reportResult(ast->identifier_token, candidates);
|
||||
}
|
||||
|
||||
@@ -310,7 +304,7 @@ bool FindUsages::visit(SimpleNameAST *ast)
|
||||
{
|
||||
const Identifier *id = identifier(ast->identifier_token);
|
||||
if (id == _id) {
|
||||
const QList<Symbol *> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
|
||||
const QList<LookupItem> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
|
||||
reportResult(ast->identifier_token, candidates);
|
||||
}
|
||||
|
||||
@@ -321,7 +315,7 @@ bool FindUsages::visit(DestructorNameAST *ast)
|
||||
{
|
||||
const Identifier *id = identifier(ast->identifier_token);
|
||||
if (id == _id) {
|
||||
const QList<Symbol *> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
|
||||
const QList<LookupItem> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
|
||||
reportResult(ast->identifier_token, candidates);
|
||||
}
|
||||
|
||||
@@ -331,7 +325,7 @@ bool FindUsages::visit(DestructorNameAST *ast)
|
||||
bool FindUsages::visit(TemplateIdAST *ast)
|
||||
{
|
||||
if (_id == identifier(ast->identifier_token)) {
|
||||
const QList<Symbol *> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
|
||||
const QList<LookupItem> candidates = _context.lookup(ast->name, scopeAt(ast->identifier_token));
|
||||
reportResult(ast->identifier_token, candidates);
|
||||
}
|
||||
|
||||
@@ -406,7 +400,7 @@ bool FindUsages::visit(ObjCSelectorAST *ast)
|
||||
if (ast->name) {
|
||||
const Identifier *id = ast->name->identifier();
|
||||
if (id == _id) {
|
||||
const QList<Symbol *> candidates = _context.lookup(ast->name, scopeAt(ast->firstToken()));
|
||||
const QList<LookupItem> candidates = _context.lookup(ast->name, scopeAt(ast->firstToken()));
|
||||
reportResult(ast->firstToken(), candidates);
|
||||
}
|
||||
}
|
||||
@@ -440,7 +434,7 @@ bool FindUsages::visit(TypenameTypeParameterAST *ast)
|
||||
const Identifier *id = name->name->identifier();
|
||||
if (id == _id) {
|
||||
unsigned start = startOfTemplateDeclaration(_templateDeclarationStack.back());
|
||||
const QList<Symbol *> candidates = _context.lookup(name->name, scopeAt(start));
|
||||
const QList<LookupItem> candidates = _context.lookup(name->name, scopeAt(start));
|
||||
reportResult(ast->name->firstToken(), candidates);
|
||||
}
|
||||
}
|
||||
@@ -454,7 +448,7 @@ bool FindUsages::visit(TemplateTypeParameterAST *ast)
|
||||
const Identifier *id = name->name->identifier();
|
||||
if (id == _id) {
|
||||
unsigned start = startOfTemplateDeclaration(_templateDeclarationStack.back());
|
||||
const QList<Symbol *> candidates = _context.lookup(name->name, scopeAt(start));
|
||||
const QList<LookupItem> candidates = _context.lookup(name->name, scopeAt(start));
|
||||
reportResult(ast->name->firstToken(), candidates);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,10 +74,10 @@ protected:
|
||||
QString matchingLine(const Token &tk) const;
|
||||
Scope *scopeAt(unsigned tokenIndex) const;
|
||||
|
||||
void reportResult(unsigned tokenIndex, const QList<Symbol *> &candidates);
|
||||
void reportResult(unsigned tokenIndex, const QList<LookupItem> &candidates);
|
||||
void reportResult(unsigned tokenIndex);
|
||||
|
||||
bool checkCandidates(const QList<Symbol *> &candidates) const;
|
||||
bool checkCandidates(const QList<LookupItem> &candidates) const;
|
||||
void checkExpression(unsigned startToken, unsigned endToken);
|
||||
|
||||
void ensureNameIsValid(NameAST *ast);
|
||||
|
||||
@@ -39,14 +39,18 @@
|
||||
#include <Scope.h>
|
||||
#include <Control.h>
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
namespace {
|
||||
const bool debug = ! qgetenv("CPLUSPLUS_LOOKUPCONTEXT_DEBUG").isEmpty();
|
||||
}
|
||||
#include <QtCore/QStack>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QVarLengthArray>
|
||||
#include <QtCore/QtDebug>
|
||||
|
||||
using namespace CPlusPlus;
|
||||
|
||||
namespace {
|
||||
const bool debug = ! qgetenv("CPLUSPLUS_LOOKUPCONTEXT_DEBUG").isEmpty();
|
||||
} // end of anonymous namespace
|
||||
|
||||
|
||||
static void addNames(const Name *name, QList<const Name *> *names, bool addAllNames = false)
|
||||
{
|
||||
if (! name)
|
||||
@@ -241,16 +245,16 @@ ClassOrNamespace *LookupContext::lookupType(Symbol *symbol) const
|
||||
return bindings()->lookupType(symbol);
|
||||
}
|
||||
|
||||
QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
|
||||
QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
|
||||
{
|
||||
QList<Symbol *> candidates;
|
||||
QList<LookupItem> candidates;
|
||||
|
||||
if (! name)
|
||||
return candidates;
|
||||
|
||||
for (; scope; scope = scope->enclosingScope()) {
|
||||
if ((name->isNameId() || name->isTemplateNameId()) && scope->isBlockScope()) {
|
||||
bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0);
|
||||
bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0, /*binding=*/ 0);
|
||||
|
||||
if (! candidates.isEmpty())
|
||||
break; // it's a local.
|
||||
@@ -274,10 +278,10 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
|
||||
|
||||
} else if (scope->isFunctionScope()) {
|
||||
Function *fun = scope->owner()->asFunction();
|
||||
bindings()->lookupInScope(name, fun->arguments(), &candidates, /*templateId = */ 0);
|
||||
bindings()->lookupInScope(name, fun->arguments(), &candidates, /*templateId = */ 0, /*binding=*/ 0);
|
||||
|
||||
for (TemplateParameters *it = fun->templateParameters(); it && candidates.isEmpty(); it = it->previous())
|
||||
bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0);
|
||||
bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0, /*binding=*/ 0);
|
||||
|
||||
if (! candidates.isEmpty())
|
||||
break; // it's an argument or a template parameter.
|
||||
@@ -295,7 +299,7 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
|
||||
|
||||
} else if (scope->isObjCMethodScope()) {
|
||||
ObjCMethod *method = scope->owner()->asObjCMethod();
|
||||
bindings()->lookupInScope(name, method->arguments(), &candidates, /*templateId = */ 0);
|
||||
bindings()->lookupInScope(name, method->arguments(), &candidates, /*templateId = */ 0, /*binding=*/ 0);
|
||||
|
||||
if (! candidates.isEmpty())
|
||||
break; // it's a formal argument.
|
||||
@@ -304,7 +308,7 @@ QList<Symbol *> LookupContext::lookup(const Name *name, Scope *scope) const
|
||||
Class *klass = scope->owner()->asClass();
|
||||
|
||||
for (TemplateParameters *it = klass->templateParameters(); it && candidates.isEmpty(); it = it->previous())
|
||||
bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0);
|
||||
bindings()->lookupInScope(name, it->scope(), &candidates, /* templateId = */ 0, /*binding=*/ 0);
|
||||
|
||||
if (! candidates.isEmpty())
|
||||
break; // it's an argument or a template parameter.
|
||||
@@ -398,19 +402,19 @@ ClassOrNamespace *ClassOrNamespace::globalNamespace() const
|
||||
return e;
|
||||
}
|
||||
|
||||
QList<Symbol *> ClassOrNamespace::find(const Name *name)
|
||||
QList<LookupItem> ClassOrNamespace::find(const Name *name)
|
||||
{
|
||||
return lookup_helper(name, false);
|
||||
}
|
||||
|
||||
QList<Symbol *> ClassOrNamespace::lookup(const Name *name)
|
||||
QList<LookupItem> ClassOrNamespace::lookup(const Name *name)
|
||||
{
|
||||
return lookup_helper(name, true);
|
||||
}
|
||||
|
||||
QList<Symbol *> ClassOrNamespace::lookup_helper(const Name *name, bool searchInEnclosingScope)
|
||||
QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchInEnclosingScope)
|
||||
{
|
||||
QList<Symbol *> result;
|
||||
QList<LookupItem> result;
|
||||
|
||||
if (name) {
|
||||
if (const QualifiedNameId *q = name->asQualifiedNameId()) {
|
||||
@@ -435,9 +439,9 @@ QList<Symbol *> ClassOrNamespace::lookup_helper(const Name *name, bool searchInE
|
||||
}
|
||||
|
||||
void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding,
|
||||
QList<Symbol *> *result,
|
||||
QSet<ClassOrNamespace *> *processed,
|
||||
const TemplateNameId *templateId)
|
||||
QList<LookupItem> *result,
|
||||
QSet<ClassOrNamespace *> *processed,
|
||||
const TemplateNameId *templateId)
|
||||
{
|
||||
if (binding && ! processed->contains(binding)) {
|
||||
processed->insert(binding);
|
||||
@@ -448,16 +452,20 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding
|
||||
if (ScopedSymbol *scoped = s->asScopedSymbol()) {
|
||||
if (Class *klass = scoped->asClass()) {
|
||||
if (const Identifier *id = klass->identifier()) {
|
||||
if (nameId && nameId->isEqualTo(id))
|
||||
result->append(klass);
|
||||
if (nameId && nameId->isEqualTo(id)) {
|
||||
LookupItem item;
|
||||
item.setDeclaration(klass);
|
||||
item.setBinding(binding);
|
||||
result->append(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
_factory->lookupInScope(name, scoped->members(), result, templateId);
|
||||
_factory->lookupInScope(name, scoped->members(), result, templateId, binding);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Enum *e, binding->enums())
|
||||
_factory->lookupInScope(name, e->members(), result, templateId);
|
||||
_factory->lookupInScope(name, e->members(), result, templateId, binding);
|
||||
|
||||
foreach (ClassOrNamespace *u, binding->usings())
|
||||
lookup_helper(name, u, result, processed, binding->_templateId);
|
||||
@@ -465,8 +473,9 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding
|
||||
}
|
||||
|
||||
void CreateBindings::lookupInScope(const Name *name, Scope *scope,
|
||||
QList<Symbol *> *result,
|
||||
const TemplateNameId *templateId)
|
||||
QList<LookupItem> *result,
|
||||
const TemplateNameId *templateId,
|
||||
ClassOrNamespace *binding)
|
||||
{
|
||||
Q_UNUSED(templateId);
|
||||
|
||||
@@ -480,7 +489,10 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
|
||||
else if (! s->name()->isEqualTo(op))
|
||||
continue;
|
||||
|
||||
result->append(s);
|
||||
LookupItem item;
|
||||
item.setDeclaration(s);
|
||||
item.setBinding(binding);
|
||||
result->append(item);
|
||||
}
|
||||
|
||||
} else if (const Identifier *id = name->identifier()) {
|
||||
@@ -490,34 +502,17 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
|
||||
else if (s->name()->isQualifiedNameId())
|
||||
continue; // skip qualified ids.
|
||||
|
||||
LookupItem item;
|
||||
item.setDeclaration(s);
|
||||
item.setBinding(binding);
|
||||
|
||||
if (templateId && (s->isDeclaration() || s->isFunction())) {
|
||||
|
||||
FullySpecifiedType ty = DeprecatedGenTemplateInstance::instantiate(templateId, s, _control);
|
||||
|
||||
if (debug) {
|
||||
Overview oo;
|
||||
oo.setShowFunctionSignatures(true);
|
||||
oo.setShowReturnTypes(true);
|
||||
qDebug() << "instantiate:" << oo(s->type(), s->name()) << "using:" << oo(templateId) << oo(ty);
|
||||
}
|
||||
|
||||
if (Declaration *decl = s->asDeclaration()) {
|
||||
Declaration *d = _control->newDeclaration(0, 0);
|
||||
d->copy(decl);
|
||||
d->setType(ty);
|
||||
result->append(d);
|
||||
continue;
|
||||
} else if (Function *fun = s->asFunction()) {
|
||||
Function *d = ty->asFunctionType();
|
||||
d->copy(fun);
|
||||
result->append(d);
|
||||
continue;
|
||||
}
|
||||
item.setType(ty); // override the type.
|
||||
}
|
||||
|
||||
result->append(s);
|
||||
result->append(item);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -987,3 +982,4 @@ bool CreateBindings::visit(ObjCMethod *)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <Type.h>
|
||||
#include <SymbolVisitor.h>
|
||||
#include <Control.h>
|
||||
#include <Name.h>
|
||||
#include <QtCore/QSet>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
@@ -57,8 +58,8 @@ public:
|
||||
|
||||
ClassOrNamespace *globalNamespace() const;
|
||||
|
||||
QList<Symbol *> lookup(const Name *name);
|
||||
QList<Symbol *> find(const Name *name);
|
||||
QList<LookupItem> lookup(const Name *name);
|
||||
QList<LookupItem> find(const Name *name);
|
||||
|
||||
ClassOrNamespace *lookupType(const Name *name);
|
||||
ClassOrNamespace *findType(const Name *name);
|
||||
@@ -76,12 +77,12 @@ private:
|
||||
void addUsing(ClassOrNamespace *u);
|
||||
void addNestedType(const Name *alias, ClassOrNamespace *e);
|
||||
|
||||
QList<Symbol *> lookup_helper(const Name *name, bool searchInEnclosingScope);
|
||||
QList<LookupItem> lookup_helper(const Name *name, bool searchInEnclosingScope);
|
||||
|
||||
void lookup_helper(const Name *name, ClassOrNamespace *binding,
|
||||
QList<Symbol *> *result,
|
||||
QSet<ClassOrNamespace *> *processed,
|
||||
const TemplateNameId *templateId);
|
||||
QList<LookupItem> *result,
|
||||
QSet<ClassOrNamespace *> *processed,
|
||||
const TemplateNameId *templateId);
|
||||
|
||||
ClassOrNamespace *lookupType_helper(const Name *name, QSet<ClassOrNamespace *> *processed,
|
||||
bool searchInEnclosingScope);
|
||||
@@ -134,8 +135,8 @@ public:
|
||||
/// Searches in \a scope for symbols with the given \a name.
|
||||
/// Store the result in \a results.
|
||||
/// \internal
|
||||
void lookupInScope(const Name *name, Scope *scope, QList<Symbol *> *result,
|
||||
const TemplateNameId *templateId);
|
||||
void lookupInScope(const Name *name, Scope *scope, QList<LookupItem> *result,
|
||||
const TemplateNameId *templateId, ClassOrNamespace *binding);
|
||||
|
||||
/// Create bindings for the symbols reachable from \a rootSymbol.
|
||||
/// \internal
|
||||
@@ -214,7 +215,7 @@ public:
|
||||
|
||||
ClassOrNamespace *globalNamespace() const;
|
||||
|
||||
QList<Symbol *> lookup(const Name *name, Scope *scope) const;
|
||||
QList<LookupItem> lookup(const Name *name, Scope *scope) const;
|
||||
ClassOrNamespace *lookupType(const Name *name, Scope *scope) const;
|
||||
ClassOrNamespace *lookupType(Symbol *symbol) const;
|
||||
ClassOrNamespace *lookupParent(Symbol *symbol) const;
|
||||
|
||||
@@ -44,11 +44,16 @@ uint CPlusPlus::qHash(const CPlusPlus::LookupItem &key)
|
||||
}
|
||||
|
||||
LookupItem::LookupItem()
|
||||
: _scope(0), _declaration(0)
|
||||
: _scope(0), _declaration(0), _binding(0)
|
||||
{ }
|
||||
|
||||
FullySpecifiedType LookupItem::type() const
|
||||
{ return _type; }
|
||||
{
|
||||
if (! _type && _declaration)
|
||||
return _declaration->type();
|
||||
|
||||
return _type;
|
||||
}
|
||||
|
||||
void LookupItem::setType(const FullySpecifiedType &type)
|
||||
{ _type = type; }
|
||||
@@ -70,9 +75,16 @@ Scope *LookupItem::scope() const
|
||||
void LookupItem::setScope(Scope *scope)
|
||||
{ _scope = scope; }
|
||||
|
||||
ClassOrNamespace *LookupItem::binding() const
|
||||
{ return _binding; }
|
||||
|
||||
void LookupItem::setBinding(ClassOrNamespace *binding)
|
||||
{ _binding = binding; }
|
||||
|
||||
bool LookupItem::operator == (const LookupItem &other) const
|
||||
{
|
||||
if (_type == other._type && _declaration == other._declaration && _scope == other._scope)
|
||||
if (_type == other._type && _declaration == other._declaration && _scope == other._scope
|
||||
&& _binding == other._binding)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class ClassOrNamespace;
|
||||
|
||||
class CPLUSPLUS_EXPORT LookupItem
|
||||
{
|
||||
public:
|
||||
@@ -59,6 +61,9 @@ public:
|
||||
/// Sets this item's scope.
|
||||
void setScope(Scope *scope);
|
||||
|
||||
ClassOrNamespace *binding() const;
|
||||
void setBinding(ClassOrNamespace *binding);
|
||||
|
||||
bool operator == (const LookupItem &other) const;
|
||||
bool operator != (const LookupItem &other) const;
|
||||
|
||||
@@ -66,6 +71,7 @@ private:
|
||||
FullySpecifiedType _type;
|
||||
Scope *_scope;
|
||||
Symbol *_declaration;
|
||||
ClassOrNamespace *_binding;
|
||||
};
|
||||
|
||||
uint qHash(const CPlusPlus::LookupItem &result);
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "LookupContext.h"
|
||||
#include "Overview.h"
|
||||
#include "DeprecatedGenTemplateInstance.h"
|
||||
#include "CppRewriter.h"
|
||||
|
||||
#include <Control.h>
|
||||
#include <AST.h>
|
||||
@@ -121,6 +122,11 @@ void ResolveExpression::addResults(const QList<Symbol *> &symbols)
|
||||
}
|
||||
}
|
||||
|
||||
void ResolveExpression::addResults(const QList<LookupItem> &items)
|
||||
{
|
||||
_results += items;
|
||||
}
|
||||
|
||||
void ResolveExpression::addResult(const FullySpecifiedType &ty, Scope *scope)
|
||||
{
|
||||
LookupItem item;
|
||||
@@ -395,7 +401,7 @@ bool ResolveExpression::visit(CompoundLiteralAST *ast)
|
||||
bool ResolveExpression::visit(QualifiedNameAST *ast)
|
||||
{
|
||||
if (const Name *name = ast->name) {
|
||||
const QList<Symbol *> candidates = _context.lookup(name, _scope);
|
||||
const QList<LookupItem> candidates = _context.lookup(name, _scope);
|
||||
addResults(candidates);
|
||||
}
|
||||
|
||||
@@ -404,14 +410,14 @@ bool ResolveExpression::visit(QualifiedNameAST *ast)
|
||||
|
||||
bool ResolveExpression::visit(SimpleNameAST *ast)
|
||||
{
|
||||
const QList<Symbol *> candidates = _context.lookup(ast->name, _scope);
|
||||
const QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
|
||||
addResults(candidates);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ResolveExpression::visit(TemplateIdAST *ast)
|
||||
{
|
||||
const QList<Symbol *> candidates = _context.lookup(ast->name, _scope);
|
||||
const QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
|
||||
addResults(candidates);
|
||||
return false;
|
||||
}
|
||||
@@ -477,7 +483,8 @@ bool ResolveExpression::visit(CallAST *ast)
|
||||
|
||||
if (NamedType *namedTy = ty->asNamedType()) {
|
||||
if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
|
||||
foreach (Symbol *overload, b->find(functionCallOp)) {
|
||||
foreach (const LookupItem &r, b->find(functionCallOp)) {
|
||||
Symbol *overload = r.declaration();
|
||||
if (Function *funTy = overload->type()->asFunctionType()) {
|
||||
if (maybeValidPrototype(funTy, actualArgumentCount)) {
|
||||
if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
|
||||
@@ -520,7 +527,8 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
|
||||
|
||||
} else if (NamedType *namedTy = ty->asNamedType()) {
|
||||
if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
|
||||
foreach (Symbol *overload, b->find(arrayAccessOp)) {
|
||||
foreach (const LookupItem &r, b->find(arrayAccessOp)) {
|
||||
Symbol *overload = r.declaration();
|
||||
if (Function *funTy = overload->type()->asFunctionType()) {
|
||||
if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
|
||||
// ### TODO: check the actual arguments
|
||||
@@ -534,6 +542,56 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
QList<LookupItem> ResolveExpression::getMembers(ClassOrNamespace *binding, const Name *memberName) const
|
||||
{
|
||||
QList<LookupItem> members;
|
||||
|
||||
const QList<LookupItem> originalMembers = binding->find(memberName);
|
||||
|
||||
foreach (const LookupItem &m, originalMembers) {
|
||||
if (! m.binding() || ! m.binding()->templateId()) {
|
||||
members.append(m);
|
||||
continue;
|
||||
}
|
||||
|
||||
Symbol *decl = m.declaration();
|
||||
|
||||
if (Class *klass = decl->enclosingSymbol()->asClass()) {
|
||||
if (klass->templateParameters() != 0) {
|
||||
SubstitutionMap map;
|
||||
|
||||
const TemplateNameId *templateId = m.binding()->templateId();
|
||||
unsigned count = qMin(klass->templateParameterCount(), templateId->templateArgumentCount());
|
||||
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
map.bind(klass->templateParameterAt(i)->name(), templateId->templateArgumentAt(i));
|
||||
}
|
||||
|
||||
SubstitutionEnvironment env;
|
||||
ContextSubstitution ctxSubst(_context, m.scope());
|
||||
|
||||
env.enter(&ctxSubst);
|
||||
env.enter(&map);
|
||||
FullySpecifiedType instantiatedTy = rewriteType(decl->type(), env, _context.control().data());
|
||||
|
||||
Overview oo;
|
||||
oo.setShowReturnTypes(true);
|
||||
oo.setShowFunctionSignatures(true);
|
||||
|
||||
qDebug() << "original:" << oo(decl->type(), decl->name()) << "inst:" << oo(instantiatedTy, decl->name());
|
||||
|
||||
LookupItem newItem;
|
||||
newItem = m;
|
||||
newItem.setType(instantiatedTy);
|
||||
members.append(newItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
bool ResolveExpression::visit(MemberAccessAST *ast)
|
||||
{
|
||||
// The candidate types for the base expression are stored in
|
||||
@@ -586,9 +644,13 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
|
||||
|
||||
} else if (ClassOrNamespace *binding = findClass(ty, scope)) {
|
||||
// lookup for overloads of operator->
|
||||
const OperatorNameId *arrowOp = control()->operatorNameId(OperatorNameId::ArrowOp);
|
||||
|
||||
foreach (Symbol *overload, binding->find(arrowOp)) {
|
||||
const OperatorNameId *arrowOp = control()->operatorNameId(OperatorNameId::ArrowOp);
|
||||
foreach (const LookupItem &r, binding->find(arrowOp)) {
|
||||
Symbol *overload = r.declaration();
|
||||
if (! overload)
|
||||
continue;
|
||||
|
||||
if (overload->type()->isFunctionType()) {
|
||||
FullySpecifiedType overloadTy = instantiate(binding->templateId(), overload);
|
||||
Function *instantiatedFunction = overloadTy->asFunctionType();
|
||||
@@ -604,14 +666,10 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
|
||||
if (ClassOrNamespace *retBinding = findClass(ptrTy->elementType(), scope))
|
||||
return retBinding;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
Overview oo;
|
||||
qDebug() << "no class for:" << oo(ptrTy->elementType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else if (accessOp == T_DOT) {
|
||||
if (replacedDotOperator) {
|
||||
@@ -663,9 +721,11 @@ bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
|
||||
}
|
||||
|
||||
if (binding) {
|
||||
foreach (Symbol *s, binding->lookup(ast->selector->name))
|
||||
foreach (const LookupItem &r, binding->lookup(ast->selector->name)) {
|
||||
Symbol *s = r.declaration();
|
||||
if (ObjCMethod *m = s->asObjCMethod())
|
||||
addResult(m->returnType(), result.scope());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,10 +59,13 @@ protected:
|
||||
QList<LookupItem> switchResults(const QList<LookupItem> &symbols);
|
||||
FullySpecifiedType instantiate(const Name *className, Symbol *candidate) const;
|
||||
|
||||
Q_DECL_DEPRECATED QList<LookupItem> getMembers(ClassOrNamespace *binding, const Name *memberName) const;
|
||||
|
||||
void thisObject();
|
||||
|
||||
void addResult(const FullySpecifiedType &ty, Scope *scope);
|
||||
void addResults(const QList<Symbol *> &symbols);
|
||||
void addResults(const QList<LookupItem> &items);
|
||||
|
||||
bool maybeValidPrototype(Function *funTy, unsigned actualArgumentCount) const;
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ SOURCES += \
|
||||
HEADERS += \
|
||||
$$PWD/SimpleLexer.h \
|
||||
$$PWD/CppDocument.h \
|
||||
$$PWD/CppRewriter.h \
|
||||
$$PWD/Overview.h \
|
||||
$$PWD/NamePrettyPrinter.h \
|
||||
$$PWD/TypeOfExpression.h \
|
||||
@@ -52,6 +53,7 @@ HEADERS += \
|
||||
SOURCES += \
|
||||
$$PWD/SimpleLexer.cpp \
|
||||
$$PWD/CppDocument.cpp \
|
||||
$$PWD/CppRewriter.cpp \
|
||||
$$PWD/Overview.cpp \
|
||||
$$PWD/NamePrettyPrinter.cpp \
|
||||
$$PWD/TypeOfExpression.cpp \
|
||||
|
||||
Reference in New Issue
Block a user