Commit d48ba551 authored by David Boddie's avatar David Boddie
Browse files

Merge branch 'master' of scm.dev.nokia.troll.no:creator/mainline

parents 68056fe7 1263babf
......@@ -31,88 +31,59 @@
#define CHECKUNDEFINEDSYMBOLS_H
#include "CppDocument.h"
#include "CppBindings.h"
#include "LookupContext.h"
#include <ASTVisitor.h>
#include <QtCore/QSet>
#include <QtCore/QByteArray>
namespace CPlusPlus {
class CPLUSPLUS_EXPORT CheckUndefinedSymbols: protected ASTVisitor
{
public:
CheckUndefinedSymbols(Document::Ptr doc);
CheckUndefinedSymbols(TranslationUnit *unit, const LookupContext &context);
virtual ~CheckUndefinedSymbols();
void setGlobalNamespaceBinding(NamespaceBindingPtr globalNamespaceBinding);
void operator()(AST *ast);
protected:
using ASTVisitor::visit;
bool isType(const Identifier *id) const;
bool isType(const QByteArray &name) const;
QList<Document::DiagnosticMessage> operator()(AST *ast);
void addType(const Name *name);
void buildTypeMap(Class *klass);
void buildMemberTypeMap(Symbol *member);
void buildTypeMap(NamespaceBinding *binding, QSet<NamespaceBinding *> *processed);
void addProtocol(const Name *name);
bool isProtocol(const QByteArray &name) const;
struct Use { // ### remove me
unsigned line;
unsigned column;
unsigned length;
FunctionDeclaratorAST *currentFunctionDeclarator() const;
CompoundStatementAST *compoundStatement() const;
bool qobjectCheck() const;
Use(unsigned line = 0, unsigned column = 0, unsigned length = 0)
: line(line), column(column), length(length) {}
};
QByteArray templateParameterName(NameAST *ast) const;
QByteArray templateParameterName(DeclarationAST *ast) const;
QList<Use> typeUsages() const;
virtual bool visit(FunctionDeclaratorAST *ast);
virtual void endVisit(FunctionDeclaratorAST *ast);
virtual bool visit(TypeofSpecifierAST *ast);
virtual bool visit(NamedTypeSpecifierAST *ast);
virtual bool visit(TemplateDeclarationAST *ast);
virtual void endVisit(TemplateDeclarationAST *);
protected:
using ASTVisitor::visit;
virtual bool visit(ClassSpecifierAST *ast);
virtual void endVisit(ClassSpecifierAST *);
bool warning(unsigned line, unsigned column, const QString &text, unsigned length = 0);
bool warning(AST *ast, const QString &text);
virtual bool visit(FunctionDefinitionAST *ast);
virtual void endVisit(FunctionDefinitionAST *ast);
void checkName(NameAST *ast);
void checkNamespace(NameAST *name);
void addTypeUsage(ClassOrNamespace *b, NameAST *ast);
void addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast);
virtual bool visit(CompoundStatementAST *ast);
virtual void endVisit(CompoundStatementAST *ast);
virtual bool visit(NamespaceAST *);
virtual bool visit(UsingDirectiveAST *);
virtual bool visit(SimpleDeclarationAST *);
virtual bool visit(NamedTypeSpecifierAST *);
virtual bool visit(SimpleDeclarationAST *ast);
virtual bool visit(BaseSpecifierAST *base);
virtual bool visit(UsingDirectiveAST *ast);
virtual bool visit(SimpleNameAST *ast);
virtual bool visit(DestructorNameAST *ast);
virtual bool visit(QualifiedNameAST *ast);
virtual bool visit(CastExpressionAST *ast);
virtual bool visit(SizeofExpressionAST *ast);
virtual bool visit(NamespaceAliasDefinitionAST *ast);
virtual bool visit(ObjCClassDeclarationAST *ast);
virtual bool visit(ObjCProtocolRefsAST *ast);
virtual bool visit(ObjCPropertyDeclarationAST *ast);
virtual bool visit(QtEnumDeclarationAST *ast);
virtual bool visit(QtFlagsDeclarationAST *ast);
virtual bool visit(QtPropertyDeclarationAST *ast);
virtual bool visit(TemplateIdAST *ast);
private:
Document::Ptr _doc;
NamespaceBindingPtr _globalNamespaceBinding;
QList<bool> _qobjectStack;
QList<FunctionDeclaratorAST *> _functionDeclaratorStack;
QList<TemplateDeclarationAST *> _templateDeclarationStack;
QList<CompoundStatementAST *> _compoundStatementStack;
QSet<QByteArray> _types;
QSet<QByteArray> _protocols;
QSet<QByteArray> _namespaceNames;
LookupContext _context;
QString _fileName;
QList<Document::DiagnosticMessage> _diagnosticMessages;
QSet<QByteArray> _potentialTypes;
QList<ScopedSymbol *> _scopes;
QList<Use> _typeUsages;
};
} // end of namespace CPlusPlus
......
This diff is collapsed.
/**************************************************************************
**
** 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 CPPBINDINGS_H
#define CPPBINDINGS_H
#include "CppDocument.h"
#include <QtCore/QList>
#include <QtCore/QSharedPointer>
#include <QtCore/QString>
#include <QtCore/QByteArray>
namespace CPlusPlus {
class Location;
class Binding;
class NamespaceBinding;
class ClassBinding;
typedef QSharedPointer<Binding> BindingPtr;
typedef QSharedPointer<ClassBinding> ClassBindingPtr;
typedef QSharedPointer<NamespaceBinding> NamespaceBindingPtr;
class CPLUSPLUS_EXPORT Location
{
public:
Location();
Location(Symbol *symbol);
Location(const StringLiteral *fileId, unsigned sourceLocation);
inline bool isValid() const
{ return _fileId != 0; }
inline operator bool() const
{ return _fileId != 0; }
inline const StringLiteral *fileId() const
{ return _fileId; }
inline unsigned sourceLocation() const
{ return _sourceLocation; }
private:
const StringLiteral *_fileId;
unsigned _sourceLocation;
};
class CPLUSPLUS_EXPORT Binding
{
Q_DISABLE_COPY(Binding)
public:
Binding() {}
virtual ~Binding() {}
virtual QByteArray qualifiedId() const = 0;
virtual NamespaceBinding *asNamespaceBinding() { return 0; }
virtual ClassBinding *asClassBinding() { return 0; }
virtual ClassBinding *findClassBinding(const Name *name, QSet<Binding *> *processed) = 0;
virtual Binding *findClassOrNamespaceBinding(const Identifier *id, QSet<Binding *> *processed) = 0;
};
class CPLUSPLUS_EXPORT NamespaceBinding: public Binding
{
public:
/// Constructs a binding with the given parent.
NamespaceBinding(NamespaceBinding *parent = 0);
/// Destroys the binding.
virtual ~NamespaceBinding();
/// Returns this binding's name.
const NameId *name() const;
/// Returns this binding's identifier.
const Identifier *identifier() const;
/// Returns the binding for the global namespace (aka ::).
NamespaceBinding *globalNamespaceBinding();
/// Returns the binding for the given namespace symbol.
NamespaceBinding *findNamespaceBinding(const Name *name);
/// Returns the binding associated with the given symbol.
NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol);
NamespaceBinding *resolveNamespace(const Location &loc,
const Name *name,
bool lookAtParent = true);
virtual ClassBinding *findClassBinding(const Name *name, QSet<Binding *> *processed);
virtual Binding *findClassOrNamespaceBinding(const Identifier *id, QSet<Binding *> *processed);
/// Helpers.
virtual QByteArray qualifiedId() const;
void dump();
virtual NamespaceBinding *asNamespaceBinding() { return this; }
static NamespaceBinding *find(Namespace *symbol, NamespaceBinding *binding);
static ClassBinding *find(Class *symbol, NamespaceBinding *binding);
private:
NamespaceBinding *findNamespaceBindingForNameId(const NameId *name,
bool lookAtParentNamespace);
NamespaceBinding *findNamespaceBindingForNameId_helper(const NameId *name,
bool lookAtParentNamespace,
QSet<NamespaceBinding *> *processed);
public: // attributes
/// This binding's parent.
NamespaceBinding *parent;
/// Binding for anonymous namespace symbols.
NamespaceBinding *anonymousNamespaceBinding;
/// This binding's connections.
QList<NamespaceBinding *> children;
/// This binding's list of using namespaces.
QList<NamespaceBinding *> usings;
/// This binding's namespace symbols.
QList<Namespace *> symbols;
QList<ClassBinding *> classBindings;
};
class CPLUSPLUS_EXPORT ClassBinding: public Binding
{
public:
ClassBinding(NamespaceBinding *parent);
ClassBinding(ClassBinding *parentClass);
virtual ~ClassBinding();
virtual ClassBinding *asClassBinding() { return this; }
/// Returns this binding's name.
const Name *name() const;
/// Returns this binding's identifier.
const Identifier *identifier() const;
virtual QByteArray qualifiedId() const;
virtual ClassBinding *findClassBinding(const Name *name, QSet<Binding *> *processed);
virtual Binding *findClassOrNamespaceBinding(const Identifier *id, QSet<Binding *> *processed);
void dump();
public: // attributes
Binding *parent;
QList<ClassBinding *> children;
/// This binding's class symbols.
QList<Class *> symbols;
/// Bindings for the base classes.
QList<ClassBinding *> baseClassBindings;
};
CPLUSPLUS_EXPORT NamespaceBindingPtr bind(Document::Ptr doc, Snapshot snapshot);
} // end of namespace CPlusPlus
#endif // CPPBINDINGS_H
......@@ -138,12 +138,14 @@ public:
public:
DiagnosticMessage(int level, const QString &fileName,
int line, int column,
const QString &text)
unsigned line, unsigned column,
const QString &text,
unsigned length = 0)
: _level(level),
_fileName(fileName),
_line(line),
_column(column),
_length(length),
_text(text)
{ }
......@@ -168,6 +170,9 @@ public:
unsigned column() const
{ return _column; }
unsigned length() const
{ return _length; }
QString text() const
{ return _text; }
......@@ -176,6 +181,7 @@ public:
QString _fileName;
unsigned _line;
unsigned _column;
unsigned _length;
QString _text;
};
......
......@@ -30,7 +30,6 @@
#include "DeprecatedLookupContext.h"
#include "ResolveExpression.h"
#include "Overview.h"
#include "CppBindings.h"
#include <CoreTypes.h>
#include <Symbols.h>
......@@ -623,142 +622,3 @@ void DeprecatedLookupContext::expand(Scope *scope,
expandObjCClass(objcKlass, visibleScopes, expandedScopes);
}
}
static void visibleClassBindings_helper(ClassBinding *classBinding,
QList<ClassBinding *> *allClassBindings,
QSet<ClassBinding *> *processed)
{
if (! classBinding)
return;
else if (processed->contains(classBinding))
return;
processed->insert(classBinding);
foreach (ClassBinding *baseClassBinding, classBinding->baseClassBindings)
visibleClassBindings_helper(baseClassBinding, allClassBindings, processed);
allClassBindings->append(classBinding);
}
static QList<ClassBinding *> visibleClassBindings(Symbol *symbol, NamespaceBinding *globalNamespace)
{
QList<ClassBinding *> classBindings;
if (! symbol)
return classBindings;
else if (Class *klass = symbol->asClass()) {
QSet<ClassBinding *> processed;
visibleClassBindings_helper(NamespaceBinding::find(klass, globalNamespace),
&classBindings, &processed);
}
return classBindings;
}
Symbol *DeprecatedLookupContext::canonicalSymbol(Symbol *symbol,
NamespaceBinding *globalNamespace)
{
Symbol *canonicalSymbol = DeprecatedLookupContext::canonicalSymbol(symbol);
if (! canonicalSymbol)
return 0;
if (const Identifier *symbolId = canonicalSymbol->identifier()) {
if (symbolId && canonicalSymbol->type()->isFunctionType()) {
Class *enclosingClass = canonicalSymbol->scope()->owner()->asClass();
const QList<ClassBinding *> classBindings = visibleClassBindings(enclosingClass, globalNamespace);
foreach (ClassBinding *baseClassBinding, classBindings) {
if (! baseClassBinding)
continue;
foreach (Class *baseClass, baseClassBinding->symbols) {
if (! baseClass)
continue;
for (Symbol *c = baseClass->members()->lookat(symbolId); c; c = c->next()) {
if (! symbolId->isEqualTo(c->identifier()))
continue;
else if (Function *f = c->type()->asFunctionType()) {
if (f->isVirtual())
return DeprecatedLookupContext::canonicalSymbol(f);
}
}
}
}
}
}
return canonicalSymbol;
}
Symbol *DeprecatedLookupContext::canonicalSymbol(const QList<Symbol *> &candidates,
NamespaceBinding *globalNamespaceBinding)
{
if (candidates.isEmpty())
return 0;
return canonicalSymbol(candidates.first(), globalNamespaceBinding);
}
Symbol *DeprecatedLookupContext::canonicalSymbol(const QList<LookupItem> &results,
NamespaceBinding *globalNamespaceBinding)
{
QList<Symbol *> candidates;
foreach (const LookupItem &result, results)
candidates.append(result.declaration()); // ### not exactly.
return canonicalSymbol(candidates, globalNamespaceBinding);
}
Symbol *DeprecatedLookupContext::canonicalSymbol(Symbol *symbol)
{
Symbol *canonical = symbol;
Class *canonicalClass = 0;
ObjCClass *canonicalObjCClass = 0;
ObjCProtocol *canonicalObjCProto = 0;
for (; symbol; symbol = symbol->next()) {
if (symbol->identifier() == canonical->identifier()) {
canonical = symbol;
if (Class *klass = symbol->asClass())
canonicalClass = klass;
else if (ObjCClass *clazz = symbol->asObjCClass())
canonicalObjCClass = clazz;
else if (ObjCProtocol *proto = symbol->asObjCProtocol())
canonicalObjCProto = proto;
}
}
if (canonicalClass) {
Q_ASSERT(canonical != 0);
if (canonical->isForwardClassDeclaration())
return canonicalClass; // prefer class declarations when available.
} else if (canonicalObjCClass) {
Q_ASSERT(canonical != 0);
if (canonical->isObjCForwardClassDeclaration())
return canonicalObjCClass;
} else if (canonicalObjCProto) {
Q_ASSERT(canonical != 0);
if (canonical->isObjCForwardProtocolDeclaration())
return canonicalObjCProto;
}
if (canonical && canonical->scope()->isClassScope()) {
Class *enclosingClass = canonical->scope()->owner()->asClass();
if (enclosingClass->identifier() == canonical->identifier())
return enclosingClass;
}
return canonical;
}
......@@ -57,15 +57,6 @@ public:
Document::Ptr document(const QString &fileName) const;
Snapshot snapshot() const;
static Symbol *canonicalSymbol(const QList<Symbol *> &candidates,
NamespaceBinding *globalNamespaceBinding);
static Symbol *canonicalSymbol(Symbol *symbol,
NamespaceBinding *globalNamespaceBinding);
static Symbol *canonicalSymbol(const QList<LookupItem> &candidates,
NamespaceBinding *globalNamespaceBinding);
QList<Symbol *> resolve(const Name *name) const
{ return resolve(name, visibleScopes()); }
......@@ -157,7 +148,6 @@ public:
QList<Scope *> *expandedScopes) const;
private:
static Symbol *canonicalSymbol(Symbol *symbol);
QList<Symbol *> resolveQualifiedNameId(const QualifiedNameId *q,
const QList<Scope *> &visibleScopes,
......
......@@ -39,6 +39,7 @@
#include <TranslationUnit.h>
#include <QtCore/QDir>
#include <QtCore/QDebug>
using namespace CPlusPlus;
......@@ -56,11 +57,6 @@ FindUsages::FindUsages(Document::Ptr doc, const Snapshot &snapshot)
typeofExpression.init(_doc, _snapshot, _context.bindings());
}
void FindUsages::setGlobalNamespaceBinding(NamespaceBindingPtr globalNamespaceBinding)
{
_globalNamespaceBinding = globalNamespaceBinding;
}
QList<Usage> FindUsages::usages() const
{ return _usages; }
......@@ -128,12 +124,14 @@ void FindUsages::reportResult(unsigned tokenIndex, const QList<Symbol *> &candid
void FindUsages::reportResult(unsigned tokenIndex)
{
if (_processed.contains(tokenIndex))
const Token &tk = tokenAt(tokenIndex);
if (tk.generated())
return;
else if (_processed.contains(tokenIndex))
return;
_processed.insert(tokenIndex);
const Token &tk = tokenAt(tokenIndex);
const QString lineText = matchingLine(tk);
unsigned line, col;
......@@ -151,61 +149,12 @@ void FindUsages::reportResult(unsigned tokenIndex)
bool FindUsages::checkCandidates(const QList<Symbol *> &candidates) const
{
if (Symbol *canonicalSymbol = DeprecatedLookupContext::canonicalSymbol(candidates, _globalNamespaceBinding.data())) {
#if 0
Symbol *c = candidates.first();
qDebug() << "*** canonical symbol:" << canonicalSymbol->fileName()
<< canonicalSymbol->line() << canonicalSymbol->column()
<< "candidates:" << candidates.size()
<< c->fileName() << c->line() << c->column();
#endif
return checkSymbol(canonicalSymbol);
}
return false;
}
bool FindUsages::checkScope(Symbol *symbol, Symbol *otherSymbol) const
{
if (! (symbol && otherSymbol))
return false;
else if (symbol->scope() == otherSymbol->scope())
return true;
else if (symbol->name() && otherSymbol->name()) {