forked from qt-creator/qt-creator
C++: improve support for anonymous classes
Fix: * highlighting * find usages * follow symbol * code completion Task-number: QTCREATORBUG-6497 Task-number: QTCREATORBUG-8963 Task-number: QTCREATORBUG-3610 Task-number: QTCREATORBUG-7579 Change-Id: I3dcaf1c515d0199c3e6bee72284fbb40064686ee Reviewed-by: Petar Perisin <petar.perisin@gmail.com> Reviewed-by: Orgad Shaneh <orgads@gmail.com> Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com> Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
committed by
Erik Verbruggen
parent
a2b2857b44
commit
080bf4ecb8
21
src/libs/3rdparty/cplusplus/AST.h
vendored
21
src/libs/3rdparty/cplusplus/AST.h
vendored
@@ -127,6 +127,7 @@ public:
|
||||
virtual AccessDeclarationAST *asAccessDeclaration() { return 0; }
|
||||
virtual AliasDeclarationAST *asAliasDeclaration() { return 0; }
|
||||
virtual AlignofExpressionAST *asAlignofExpression() { return 0; }
|
||||
virtual AnonymousNameAST *asAnonymousName() { return 0; }
|
||||
virtual ArrayAccessAST *asArrayAccess() { return 0; }
|
||||
virtual ArrayDeclaratorAST *asArrayDeclarator() { return 0; }
|
||||
virtual ArrayInitializerAST *asArrayInitializer() { return 0; }
|
||||
@@ -2267,6 +2268,26 @@ protected:
|
||||
virtual bool match0(AST *, ASTMatcher *);
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT AnonymousNameAST: public NameAST
|
||||
{
|
||||
public:
|
||||
unsigned class_token;
|
||||
public:
|
||||
AnonymousNameAST()
|
||||
: class_token(0)
|
||||
{}
|
||||
|
||||
virtual AnonymousNameAST *asAnonymousName() { return this; }
|
||||
virtual unsigned firstToken() const { return 0; }
|
||||
virtual unsigned lastToken() const { return 0; }
|
||||
|
||||
virtual AnonymousNameAST *clone(MemoryPool *pool) const;
|
||||
|
||||
protected:
|
||||
virtual void accept0(ASTVisitor *visitor);
|
||||
virtual bool match0(AST *, ASTMatcher *);
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT SimpleNameAST: public NameAST
|
||||
{
|
||||
public:
|
||||
|
7
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
7
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
@@ -824,6 +824,13 @@ ConversionFunctionIdAST *ConversionFunctionIdAST::clone(MemoryPool *pool) const
|
||||
return ast;
|
||||
}
|
||||
|
||||
AnonymousNameAST *AnonymousNameAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
AnonymousNameAST *ast = new (pool) AnonymousNameAST;
|
||||
ast->class_token = class_token;
|
||||
return ast;
|
||||
}
|
||||
|
||||
SimpleNameAST *SimpleNameAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
SimpleNameAST *ast = new (pool) SimpleNameAST;
|
||||
|
8
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
8
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
@@ -552,6 +552,14 @@ bool ConversionFunctionIdAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AnonymousNameAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
{
|
||||
if (AnonymousNameAST *_other = pattern->asAnonymousName())
|
||||
return matcher->match(this, _other);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SimpleNameAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
{
|
||||
if (SimpleNameAST *_other = pattern->asSimpleName())
|
||||
|
10
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
10
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
@@ -1403,6 +1403,16 @@ bool ASTMatcher::match(ConversionFunctionIdAST *node, ConversionFunctionIdAST *p
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ASTMatcher::match(AnonymousNameAST *node, AnonymousNameAST *pattern)
|
||||
{
|
||||
(void) node;
|
||||
(void) pattern;
|
||||
|
||||
pattern->class_token = node->class_token;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ASTMatcher::match(SimpleNameAST *node, SimpleNameAST *pattern)
|
||||
{
|
||||
(void) node;
|
||||
|
1
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
1
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
@@ -34,6 +34,7 @@ public:
|
||||
virtual bool match(AccessDeclarationAST *node, AccessDeclarationAST *pattern);
|
||||
virtual bool match(AliasDeclarationAST *node, AliasDeclarationAST *pattern);
|
||||
virtual bool match(AlignofExpressionAST *node, AlignofExpressionAST *pattern);
|
||||
virtual bool match(AnonymousNameAST *node, AnonymousNameAST *pattern);
|
||||
virtual bool match(ArrayAccessAST *node, ArrayAccessAST *pattern);
|
||||
virtual bool match(ArrayDeclaratorAST *node, ArrayDeclaratorAST *pattern);
|
||||
virtual bool match(ArrayInitializerAST *node, ArrayInitializerAST *pattern);
|
||||
|
@@ -543,6 +543,12 @@ public:
|
||||
return __ast;
|
||||
}
|
||||
|
||||
AnonymousNameAST *AnonymousName()
|
||||
{
|
||||
AnonymousNameAST *__ast = new (&pool) AnonymousNameAST;
|
||||
return __ast;
|
||||
}
|
||||
|
||||
SimpleNameAST *SimpleName()
|
||||
{
|
||||
SimpleNameAST *__ast = new (&pool) SimpleNameAST;
|
||||
|
7
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
7
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
@@ -596,6 +596,13 @@ void ConversionFunctionIdAST::accept0(ASTVisitor *visitor)
|
||||
visitor->endVisit(this);
|
||||
}
|
||||
|
||||
void AnonymousNameAST::accept0(ASTVisitor *visitor)
|
||||
{
|
||||
if (visitor->visit(this)) {
|
||||
}
|
||||
visitor->endVisit(this);
|
||||
}
|
||||
|
||||
void SimpleNameAST::accept0(ASTVisitor *visitor)
|
||||
{
|
||||
if (visitor->visit(this)) {
|
||||
|
2
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
2
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
@@ -76,6 +76,7 @@ public:
|
||||
virtual bool visit(AccessDeclarationAST *) { return true; }
|
||||
virtual bool visit(AliasDeclarationAST *) { return true; }
|
||||
virtual bool visit(AlignofExpressionAST *) { return true; }
|
||||
virtual bool visit(AnonymousNameAST *) { return true; }
|
||||
virtual bool visit(ArrayAccessAST *) { return true; }
|
||||
virtual bool visit(ArrayDeclaratorAST *) { return true; }
|
||||
virtual bool visit(ArrayInitializerAST *) { return true; }
|
||||
@@ -221,6 +222,7 @@ public:
|
||||
virtual void endVisit(AccessDeclarationAST *) {}
|
||||
virtual void endVisit(AliasDeclarationAST *) {}
|
||||
virtual void endVisit(AlignofExpressionAST *) {}
|
||||
virtual void endVisit(AnonymousNameAST *) {}
|
||||
virtual void endVisit(ArrayAccessAST *) {}
|
||||
virtual void endVisit(ArrayDeclaratorAST *) {}
|
||||
virtual void endVisit(ArrayInitializerAST *) {}
|
||||
|
1
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
1
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
@@ -34,6 +34,7 @@ class ASTMatcher;
|
||||
class AccessDeclarationAST;
|
||||
class AliasDeclarationAST;
|
||||
class AlignofExpressionAST;
|
||||
class AnonymousNameAST;
|
||||
class ArrayAccessAST;
|
||||
class ArrayDeclaratorAST;
|
||||
class ArrayInitializerAST;
|
||||
|
8
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
8
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
@@ -2614,6 +2614,12 @@ bool Bind::visit(ConversionFunctionIdAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Bind::visit(AnonymousNameAST *ast)
|
||||
{
|
||||
ast->name = _name = control()->anonymousNameId(ast->class_token);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Bind::visit(SimpleNameAST *ast)
|
||||
{
|
||||
const Identifier *id = identifier(ast->identifier_token);
|
||||
@@ -2896,7 +2902,7 @@ bool Bind::visit(ClassSpecifierAST *ast)
|
||||
|
||||
const Name *className = this->name(ast->name);
|
||||
|
||||
if (ast->name) {
|
||||
if (ast->name && ! ast->name->asAnonymousName()) {
|
||||
sourceLocation = location(ast->name, sourceLocation);
|
||||
startScopeOffset = tokenAt(sourceLocation).end(); // at the end of the class name
|
||||
|
||||
|
1
src/libs/3rdparty/cplusplus/Bind.h
vendored
1
src/libs/3rdparty/cplusplus/Bind.h
vendored
@@ -237,6 +237,7 @@ protected:
|
||||
virtual bool visit(QualifiedNameAST *ast);
|
||||
virtual bool visit(OperatorFunctionIdAST *ast);
|
||||
virtual bool visit(ConversionFunctionIdAST *ast);
|
||||
virtual bool visit(AnonymousNameAST *ast);
|
||||
virtual bool visit(SimpleNameAST *ast);
|
||||
virtual bool visit(DestructorNameAST *ast);
|
||||
virtual bool visit(TemplateIdAST *ast);
|
||||
|
@@ -73,6 +73,7 @@ class SymbolTable;
|
||||
class NameVisitor;
|
||||
class Name;
|
||||
class Identifier;
|
||||
class AnonymousNameId;
|
||||
class TemplateNameId;
|
||||
class DestructorNameId;
|
||||
class OperatorNameId;
|
||||
|
17
src/libs/3rdparty/cplusplus/Control.cpp
vendored
17
src/libs/3rdparty/cplusplus/Control.cpp
vendored
@@ -101,6 +101,14 @@ template <> struct Compare<ArrayType>
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct Compare<AnonymousNameId>
|
||||
{
|
||||
bool operator()(const AnonymousNameId &name, const AnonymousNameId &otherName) const
|
||||
{
|
||||
return name.classTokenIndex() < otherName.classTokenIndex();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct Compare<DestructorNameId>
|
||||
{
|
||||
bool operator()(const DestructorNameId &name, const DestructorNameId &otherName) const
|
||||
@@ -219,6 +227,11 @@ public:
|
||||
delete_array_entries(symbols);
|
||||
}
|
||||
|
||||
const AnonymousNameId *findOrInsertAnonymousNameId(unsigned classTokenIndex)
|
||||
{
|
||||
return anonymousNameIds.intern(AnonymousNameId(classTokenIndex));
|
||||
}
|
||||
|
||||
template <typename _Iterator>
|
||||
const TemplateNameId *findOrInsertTemplateNameId(const Identifier *id, bool isSpecialization,
|
||||
_Iterator first, _Iterator last)
|
||||
@@ -475,6 +488,7 @@ public:
|
||||
// ### replace std::map with lookup tables. ASAP!
|
||||
|
||||
// names
|
||||
Table<AnonymousNameId> anonymousNameIds;
|
||||
Table<DestructorNameId> destructorNameIds;
|
||||
Table<OperatorNameId> operatorNameIds;
|
||||
Table<ConversionNameId> conversionNameIds;
|
||||
@@ -550,6 +564,9 @@ DiagnosticClient *Control::diagnosticClient() const
|
||||
void Control::setDiagnosticClient(DiagnosticClient *diagnosticClient)
|
||||
{ d->diagnosticClient = diagnosticClient; }
|
||||
|
||||
const AnonymousNameId *Control::anonymousNameId(unsigned classTokenIndex)
|
||||
{ return d->findOrInsertAnonymousNameId(classTokenIndex); }
|
||||
|
||||
const OperatorNameId *Control::findOperatorNameId(OperatorNameId::Kind operatorId) const
|
||||
{
|
||||
Table<OperatorNameId>::const_iterator i = d->operatorNameIds.find(operatorId);
|
||||
|
3
src/libs/3rdparty/cplusplus/Control.h
vendored
3
src/libs/3rdparty/cplusplus/Control.h
vendored
@@ -49,6 +49,9 @@ public:
|
||||
DiagnosticClient *diagnosticClient() const;
|
||||
void setDiagnosticClient(DiagnosticClient *diagnosticClient);
|
||||
|
||||
/// Returns the canonical anonymous name id
|
||||
const AnonymousNameId *anonymousNameId(unsigned classTokenIndex);
|
||||
|
||||
/// Returns the canonical template name id.
|
||||
const TemplateNameId *templateNameId(const Identifier *id,
|
||||
bool isSpecialization,
|
||||
|
3
src/libs/3rdparty/cplusplus/Name.cpp
vendored
3
src/libs/3rdparty/cplusplus/Name.cpp
vendored
@@ -36,6 +36,9 @@ Name::~Name()
|
||||
bool Name::isNameId() const
|
||||
{ return asNameId() != 0; }
|
||||
|
||||
bool Name::isAnonymousNameId() const
|
||||
{ return asAnonymousNameId() != 0; }
|
||||
|
||||
bool Name::isTemplateNameId() const
|
||||
{ return asTemplateNameId() != 0; }
|
||||
|
||||
|
2
src/libs/3rdparty/cplusplus/Name.h
vendored
2
src/libs/3rdparty/cplusplus/Name.h
vendored
@@ -36,6 +36,7 @@ public:
|
||||
virtual const Identifier *identifier() const = 0;
|
||||
|
||||
bool isNameId() const;
|
||||
bool isAnonymousNameId() const;
|
||||
bool isTemplateNameId() const;
|
||||
bool isDestructorNameId() const;
|
||||
bool isOperatorNameId() const;
|
||||
@@ -44,6 +45,7 @@ public:
|
||||
bool isSelectorNameId() const;
|
||||
|
||||
virtual const Identifier *asNameId() const { return 0; }
|
||||
virtual const AnonymousNameId *asAnonymousNameId() const { return 0; }
|
||||
virtual const TemplateNameId *asTemplateNameId() const { return 0; }
|
||||
virtual const DestructorNameId *asDestructorNameId() const { return 0; }
|
||||
virtual const OperatorNameId *asOperatorNameId() const { return 0; }
|
||||
|
1
src/libs/3rdparty/cplusplus/NameVisitor.h
vendored
1
src/libs/3rdparty/cplusplus/NameVisitor.h
vendored
@@ -40,6 +40,7 @@ public:
|
||||
virtual bool preVisit(const Name *) { return true; }
|
||||
virtual void postVisit(const Name *) {}
|
||||
|
||||
virtual void visit(const AnonymousNameId *) {}
|
||||
virtual void visit(const Identifier *) {}
|
||||
virtual void visit(const TemplateNameId *) {}
|
||||
virtual void visit(const DestructorNameId *) {}
|
||||
|
26
src/libs/3rdparty/cplusplus/Names.cpp
vendored
26
src/libs/3rdparty/cplusplus/Names.cpp
vendored
@@ -249,3 +249,29 @@ bool SelectorNameId::isEqualTo(const Name *other) const
|
||||
return true;
|
||||
}
|
||||
|
||||
AnonymousNameId::AnonymousNameId(unsigned classTokenIndex)
|
||||
: _classTokenIndex(classTokenIndex)
|
||||
{ }
|
||||
|
||||
AnonymousNameId::~AnonymousNameId()
|
||||
{ }
|
||||
|
||||
unsigned AnonymousNameId::classTokenIndex() const
|
||||
{
|
||||
return _classTokenIndex;
|
||||
}
|
||||
|
||||
void AnonymousNameId::accept0(NameVisitor *visitor) const
|
||||
{ visitor->visit(this); }
|
||||
|
||||
const Identifier *AnonymousNameId::identifier() const
|
||||
{ return 0; }
|
||||
|
||||
bool AnonymousNameId::isEqualTo(const Name *other) const
|
||||
{
|
||||
if (other) {
|
||||
const AnonymousNameId *c = other->asAnonymousNameId();
|
||||
return (c && this->_classTokenIndex == c->_classTokenIndex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
23
src/libs/3rdparty/cplusplus/Names.h
vendored
23
src/libs/3rdparty/cplusplus/Names.h
vendored
@@ -253,6 +253,29 @@ private:
|
||||
bool _hasArguments;
|
||||
};
|
||||
|
||||
class CPLUSPLUS_EXPORT AnonymousNameId: public Name
|
||||
{
|
||||
public:
|
||||
AnonymousNameId(unsigned classTokenIndex);
|
||||
virtual ~AnonymousNameId();
|
||||
|
||||
unsigned classTokenIndex() const;
|
||||
|
||||
virtual const Identifier *identifier() const;
|
||||
virtual bool isEqualTo(const Name *other) const;
|
||||
|
||||
virtual const AnonymousNameId *asAnonymousNameId() const
|
||||
{ return this; }
|
||||
|
||||
protected:
|
||||
virtual void accept0(NameVisitor *visitor) const;
|
||||
|
||||
private:
|
||||
unsigned _classTokenIndex;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace CPlusPlus
|
||||
|
||||
#endif // CPLUSPLUS_NAMES_H
|
||||
|
6
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
6
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -2003,6 +2003,12 @@ bool Parser::parseClassSpecifier(SpecifierListAST *&node)
|
||||
NameAST *name = 0;
|
||||
parseName(name);
|
||||
|
||||
if (! name && LA() == T_LBRACE && (LA(0) == T_CLASS || LA(0) == T_STRUCT || LA(0) == T_UNION || LA(0) == T_ENUM)) {
|
||||
AnonymousNameAST *ast = new (_pool) AnonymousNameAST;
|
||||
ast->class_token = classkey_token;
|
||||
name = ast;
|
||||
}
|
||||
|
||||
bool parsed = false;
|
||||
|
||||
const bool previousInFunctionBody = _inFunctionBody;
|
||||
|
@@ -60,7 +60,7 @@ static void addNames(const Name *name, QList<const Name *> *names, bool addAllNa
|
||||
else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
|
||||
addNames(q->base(), names);
|
||||
addNames(q->name(), names, addAllNames);
|
||||
} else if (addAllNames || name->isNameId() || name->isTemplateNameId()) {
|
||||
} else if (addAllNames || name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
|
||||
names->append(name);
|
||||
}
|
||||
}
|
||||
@@ -716,7 +716,7 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
|
||||
} else if (! processed->contains(this)) {
|
||||
processed->insert(this);
|
||||
|
||||
if (name->isNameId() || name->isTemplateNameId()) {
|
||||
if (name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
|
||||
flush();
|
||||
|
||||
foreach (Symbol *s, symbols()) {
|
||||
@@ -798,10 +798,26 @@ ClassOrNamespace *ClassOrNamespace::findSpecializationWithPointer(const Template
|
||||
ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespace *origin)
|
||||
{
|
||||
Q_ASSERT(name != 0);
|
||||
Q_ASSERT(name->isNameId() || name->isTemplateNameId());
|
||||
Q_ASSERT(name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId());
|
||||
|
||||
const_cast<ClassOrNamespace *>(this)->flush();
|
||||
|
||||
const AnonymousNameId *anonymousNameId = name->asAnonymousNameId();
|
||||
if (anonymousNameId) {
|
||||
QHash<const AnonymousNameId *, ClassOrNamespace *>::const_iterator cit
|
||||
= _anonymouses.find(anonymousNameId);
|
||||
if (cit != _anonymouses.end()) {
|
||||
return cit.value();
|
||||
} else {
|
||||
ClassOrNamespace *newAnonymous = _factory->allocClassOrNamespace(this);
|
||||
#ifdef DEBUG_LOOKUP
|
||||
newAnonymous->_name = anonymousNameId;
|
||||
#endif // DEBUG_LOOKUP
|
||||
_anonymouses[anonymousNameId] = newAnonymous;
|
||||
return newAnonymous;
|
||||
}
|
||||
}
|
||||
|
||||
Table::const_iterator it = _classOrNamespaces.find(name);
|
||||
if (it == _classOrNamespaces.end())
|
||||
return 0;
|
||||
@@ -1201,7 +1217,7 @@ ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name, ClassOrNa
|
||||
|
||||
return findOrCreateType(q->base(), origin)->findOrCreateType(q->name(), origin);
|
||||
|
||||
} else if (name->isNameId() || name->isTemplateNameId()) {
|
||||
} else if (name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
|
||||
ClassOrNamespace *e = nestedType(name, origin);
|
||||
|
||||
if (! e) {
|
||||
@@ -1470,7 +1486,7 @@ bool CreateBindings::visit(NamespaceAlias *a)
|
||||
return false;
|
||||
|
||||
} else if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(a->namespaceName())) {
|
||||
if (a->name()->isNameId() || a->name()->isTemplateNameId())
|
||||
if (a->name()->isNameId() || a->name()->isTemplateNameId() || a->name()->isAnonymousNameId())
|
||||
_currentClassOrNamespace->addNestedType(a->name(), e);
|
||||
|
||||
} else if (false) {
|
||||
|
@@ -131,6 +131,7 @@ private:
|
||||
QSharedPointer<Control> _control;
|
||||
TemplateNameIdTable _specializations;
|
||||
QMap<const TemplateNameId *, ClassOrNamespace *> _instantiations;
|
||||
QHash<const AnonymousNameId *, ClassOrNamespace *> _anonymouses;
|
||||
|
||||
QHash<Internal::FullyQualifiedName, Symbol *> *_scopeLookupCache;
|
||||
|
||||
|
@@ -268,3 +268,8 @@ void NamePrettyPrinter::visit(const SelectorNameId *name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NamePrettyPrinter::visit(const AnonymousNameId *name)
|
||||
{
|
||||
_name = QString(QLatin1String("Anonymous:%1")).arg(name->classTokenIndex());
|
||||
}
|
||||
|
@@ -57,6 +57,7 @@ protected:
|
||||
virtual void visit(const ConversionNameId *name);
|
||||
virtual void visit(const QualifiedNameId *name);
|
||||
virtual void visit(const SelectorNameId *name);
|
||||
virtual void visit(const AnonymousNameId *name);
|
||||
|
||||
private:
|
||||
const Overview *_overview;
|
||||
|
@@ -188,6 +188,9 @@ private slots:
|
||||
void operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG9006();
|
||||
void test_checksymbols_templated_functions();
|
||||
void test_checksymbols_QTCREATORBUG9098();
|
||||
void test_checksymbols_AnonymousClass();
|
||||
void test_checksymbols_AnonymousClass_insideNamespace();
|
||||
void test_checksymbols_AnonymousClass_QTCREATORBUG8963();
|
||||
};
|
||||
|
||||
void tst_CheckSymbols::test_checksymbols_TypeUse()
|
||||
@@ -1421,6 +1424,28 @@ void tst_CheckSymbols::test_checksymbols_templated_functions()
|
||||
TestData::check(source, expectedUses);
|
||||
}
|
||||
|
||||
void tst_CheckSymbols::test_checksymbols_AnonymousClass()
|
||||
{
|
||||
const QByteArray source =
|
||||
"struct\n"
|
||||
"{\n"
|
||||
" int foo;\n"
|
||||
"} Foo;\n"
|
||||
"\n"
|
||||
"void fun()\n"
|
||||
"{\n"
|
||||
" foo = 3;\n"
|
||||
"}\n"
|
||||
;
|
||||
|
||||
const QList<Use> expectedUses = QList<Use>()
|
||||
<< Use(3, 7, 3, CppHighlightingSupport::FieldUse)
|
||||
<< Use(6, 6, 3, CppHighlightingSupport::FunctionUse)
|
||||
;
|
||||
|
||||
TestData::check(source, expectedUses);
|
||||
}
|
||||
|
||||
void tst_CheckSymbols::test_checksymbols_QTCREATORBUG9098()
|
||||
{
|
||||
const QByteArray source =
|
||||
@@ -1460,5 +1485,87 @@ void tst_CheckSymbols::test_checksymbols_QTCREATORBUG9098()
|
||||
TestData::check(source, expectedUses);
|
||||
}
|
||||
|
||||
void tst_CheckSymbols::test_checksymbols_AnonymousClass_insideNamespace()
|
||||
{
|
||||
const QByteArray source =
|
||||
"struct { int foo1; } Foo1;\n"
|
||||
"void bar1()\n"
|
||||
"{\n"
|
||||
" Foo1.foo1 = 42;\n"
|
||||
"}\n"
|
||||
"namespace Ns1 {\n"
|
||||
" struct { int foo2; } Foo2;\n"
|
||||
" void bar2()\n"
|
||||
" {\n"
|
||||
" Foo2.foo2 = 42;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"namespace Ns2 {\n"
|
||||
" struct {\n"
|
||||
" struct { struct { int foo3; }; };\n"
|
||||
" void func() { foo3 = 42; }\n"
|
||||
" } Foo3;\n"
|
||||
" void bar3()\n"
|
||||
" {\n"
|
||||
" Foo3.foo3 = 42;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
;
|
||||
|
||||
const QList<Use> expectedUses = QList<Use>()
|
||||
<< Use(1, 14, 4, CppHighlightingSupport::FieldUse)
|
||||
<< Use(2, 6, 4, CppHighlightingSupport::FunctionUse)
|
||||
<< Use(4, 8, 4, CppHighlightingSupport::FieldUse)
|
||||
<< Use(6, 11, 3, CppHighlightingSupport::TypeUse)
|
||||
<< Use(7, 16, 4, CppHighlightingSupport::FieldUse)
|
||||
<< Use(8, 8, 4, CppHighlightingSupport::FunctionUse)
|
||||
<< Use(10, 10, 4, CppHighlightingSupport::FieldUse)
|
||||
<< Use(13, 11, 3, CppHighlightingSupport::TypeUse)
|
||||
<< Use(15, 27, 4, CppHighlightingSupport::FieldUse)
|
||||
<< Use(16, 10, 4, CppHighlightingSupport::FunctionUse)
|
||||
<< Use(18, 8, 4, CppHighlightingSupport::FunctionUse)
|
||||
;
|
||||
|
||||
TestData::check(source, expectedUses);
|
||||
}
|
||||
|
||||
void tst_CheckSymbols::test_checksymbols_AnonymousClass_QTCREATORBUG8963()
|
||||
{
|
||||
const QByteArray source =
|
||||
"typedef enum {\n"
|
||||
" FIRST\n"
|
||||
"} isNotInt;\n"
|
||||
"typedef struct {\n"
|
||||
" int isint;\n"
|
||||
" int isNotInt;\n"
|
||||
"} Struct;\n"
|
||||
"void foo()\n"
|
||||
"{\n"
|
||||
" Struct s;\n"
|
||||
" s.isint;\n"
|
||||
" s.isNotInt;\n"
|
||||
" FIRST;\n"
|
||||
"}\n"
|
||||
;
|
||||
|
||||
const QList<Use> expectedUses = QList<Use>()
|
||||
<< Use(2, 5, 5, CppHighlightingSupport::EnumerationUse)
|
||||
<< Use(3, 3, 8, CppHighlightingSupport::TypeUse)
|
||||
<< Use(5, 9, 5, CppHighlightingSupport::FieldUse)
|
||||
<< Use(6, 9, 8, CppHighlightingSupport::FieldUse)
|
||||
<< Use(7, 3, 6, CppHighlightingSupport::TypeUse)
|
||||
<< Use(8, 6, 3, CppHighlightingSupport::FunctionUse)
|
||||
<< Use(10, 5, 6, CppHighlightingSupport::TypeUse)
|
||||
<< Use(10, 12, 1, CppHighlightingSupport::LocalUse)
|
||||
<< Use(11, 5, 1, CppHighlightingSupport::LocalUse)
|
||||
<< Use(11, 7, 5, CppHighlightingSupport::FieldUse)
|
||||
<< Use(12, 5, 1, CppHighlightingSupport::LocalUse)
|
||||
<< Use(12, 7, 8, CppHighlightingSupport::FieldUse)
|
||||
<< Use(13, 5, 5, CppHighlightingSupport::EnumerationUse)
|
||||
;
|
||||
|
||||
TestData::check(source, expectedUses);
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_CheckSymbols)
|
||||
#include "tst_checksymbols.moc"
|
||||
|
@@ -96,6 +96,8 @@ private Q_SLOTS:
|
||||
void instantiateTemplateWithNestedClass();
|
||||
void operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG9006();
|
||||
void operatorArrowOfNestedClassOfTemplateClass_QTCREATORBUG9005();
|
||||
void anonymousClass_QTCREATORBUG8963();
|
||||
|
||||
};
|
||||
|
||||
void tst_FindUsages::inlineMethod()
|
||||
@@ -475,7 +477,6 @@ void tst_FindUsages::operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG90
|
||||
|
||||
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||
QCOMPARE(doc->globalSymbolCount(), 3U);
|
||||
|
||||
Snapshot snapshot;
|
||||
snapshot.insert(doc);
|
||||
|
||||
@@ -488,6 +489,50 @@ void tst_FindUsages::operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG90
|
||||
|
||||
FindUsages findUsages(src, doc, snapshot);
|
||||
findUsages(fooDeclaration);
|
||||
|
||||
QCOMPARE(findUsages.usages().size(), 2);
|
||||
}
|
||||
|
||||
void tst_FindUsages::anonymousClass_QTCREATORBUG8963()
|
||||
{
|
||||
const QByteArray src =
|
||||
"typedef enum {\n"
|
||||
" FIRST\n"
|
||||
"} isNotInt;\n"
|
||||
"typedef struct {\n"
|
||||
" int isint;\n"
|
||||
" int isNotInt;\n"
|
||||
"} Struct;\n"
|
||||
"void foo()\n"
|
||||
"{\n"
|
||||
" Struct s;\n"
|
||||
" s.isint;\n"
|
||||
" s.isNotInt;\n"
|
||||
" FIRST;\n"
|
||||
"}\n"
|
||||
;
|
||||
|
||||
Document::Ptr doc = Document::create("anonymousClass_QTCREATORBUG8963");
|
||||
doc->setUtf8Source(src);
|
||||
doc->parse();
|
||||
doc->check();
|
||||
|
||||
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||
QCOMPARE(doc->globalSymbolCount(), 5U);
|
||||
|
||||
Snapshot snapshot;
|
||||
snapshot.insert(doc);
|
||||
|
||||
Class *structSymbol = doc->globalSymbolAt(2)->asClass();
|
||||
QVERIFY(structSymbol);
|
||||
QCOMPARE(structSymbol->memberCount(), 2U);
|
||||
Declaration *isNotIntDeclaration = structSymbol->memberAt(1)->asDeclaration();
|
||||
QVERIFY(isNotIntDeclaration);
|
||||
QCOMPARE(isNotIntDeclaration->name()->identifier()->chars(), "isNotInt");
|
||||
|
||||
FindUsages findUsages(src, doc, snapshot);
|
||||
findUsages(isNotIntDeclaration);
|
||||
|
||||
QCOMPARE(findUsages.usages().size(), 2);
|
||||
}
|
||||
|
||||
|
@@ -796,6 +796,13 @@ virtual bool visit(ConversionFunctionIdAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool visit(AnonymousNameAST *ast)
|
||||
{
|
||||
if (ast->class_token)
|
||||
terminal(ast->class_token, ast);
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool visit(SimpleNameAST *ast)
|
||||
{
|
||||
if (ast->identifier_token)
|
||||
|
Reference in New Issue
Block a user