forked from qt-creator/qt-creator
Some initial support for template parameters in our semantic highlighter.
This commit is contained in:
@@ -137,6 +137,12 @@ protected:
|
|||||||
|
|
||||||
virtual bool visit(Function *symbol)
|
virtual bool visit(Function *symbol)
|
||||||
{
|
{
|
||||||
|
for (TemplateParameters *p = symbol->templateParameters(); p; p = p->previous()) {
|
||||||
|
Scope *scope = p->scope();
|
||||||
|
for (unsigned i = 0; i < scope->symbolCount(); ++i)
|
||||||
|
accept(scope->symbolAt(i));
|
||||||
|
}
|
||||||
|
|
||||||
addScope(symbol);
|
addScope(symbol);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -183,6 +189,12 @@ protected:
|
|||||||
|
|
||||||
virtual bool visit(Class *symbol)
|
virtual bool visit(Class *symbol)
|
||||||
{
|
{
|
||||||
|
for (TemplateParameters *p = symbol->templateParameters(); p; p = p->previous()) {
|
||||||
|
Scope *scope = p->scope();
|
||||||
|
for (unsigned i = 0; i < scope->symbolCount(); ++i)
|
||||||
|
accept(scope->symbolAt(i));
|
||||||
|
}
|
||||||
|
|
||||||
addScope(symbol);
|
addScope(symbol);
|
||||||
addType(symbol->name());
|
addType(symbol->name());
|
||||||
return true;
|
return true;
|
||||||
@@ -190,6 +202,12 @@ protected:
|
|||||||
|
|
||||||
virtual bool visit(ForwardClassDeclaration *symbol)
|
virtual bool visit(ForwardClassDeclaration *symbol)
|
||||||
{
|
{
|
||||||
|
for (TemplateParameters *p = symbol->templateParameters(); p; p = p->previous()) {
|
||||||
|
Scope *scope = p->scope();
|
||||||
|
for (unsigned i = 0; i < scope->symbolCount(); ++i)
|
||||||
|
accept(scope->symbolAt(i));
|
||||||
|
}
|
||||||
|
|
||||||
addType(symbol->name());
|
addType(symbol->name());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -326,18 +344,15 @@ void CheckUndefinedSymbols::checkNamespace(NameAST *name)
|
|||||||
void CheckUndefinedSymbols::checkName(NameAST *ast)
|
void CheckUndefinedSymbols::checkName(NameAST *ast)
|
||||||
{
|
{
|
||||||
if (ast->name) {
|
if (ast->name) {
|
||||||
const QByteArray id = QByteArray::fromRawData(ast->name->identifier()->chars(), // ### move
|
if (const Identifier *ident = ast->name->identifier()) {
|
||||||
ast->name->identifier()->size());
|
const QByteArray id = QByteArray::fromRawData(ident->chars(), ident->size());
|
||||||
if (_potentialTypes.contains(id)) {
|
if (_potentialTypes.contains(id)) {
|
||||||
const unsigned tokenOffset = tokenAt(ast->firstToken()).offset;
|
Scope *scope = findScope(ast);
|
||||||
Scope *scope = CollectTypes::findScope(tokenOffset, _scopes); // ### move
|
|
||||||
if (! scope)
|
|
||||||
scope = _context.thisDocument()->globalSymbols();
|
|
||||||
|
|
||||||
const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
|
const QList<Symbol *> candidates = _context.lookup(ast->name, scope);
|
||||||
addTypeUsage(candidates, ast);
|
addTypeUsage(candidates, ast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckUndefinedSymbols::visit(SimpleNameAST *ast)
|
bool CheckUndefinedSymbols::visit(SimpleNameAST *ast)
|
||||||
@@ -354,34 +369,24 @@ bool CheckUndefinedSymbols::visit(TemplateIdAST *ast)
|
|||||||
|
|
||||||
bool CheckUndefinedSymbols::visit(DestructorNameAST *ast)
|
bool CheckUndefinedSymbols::visit(DestructorNameAST *ast)
|
||||||
{
|
{
|
||||||
if (ast->name) {
|
checkName(ast);
|
||||||
const QByteArray id = QByteArray::fromRawData(ast->name->identifier()->chars(), // ### move
|
|
||||||
ast->name->identifier()->size());
|
|
||||||
if (_potentialTypes.contains(id)) {
|
|
||||||
Scope *scope = CollectTypes::findScope(tokenAt(ast->firstToken()).offset, _scopes); // ### move
|
|
||||||
if (! scope)
|
|
||||||
scope = _context.thisDocument()->globalSymbols();
|
|
||||||
|
|
||||||
ClassOrNamespace *b = _context.lookupType(ast->name, scope);
|
|
||||||
addTypeUsage(b, ast);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckUndefinedSymbols::visit(QualifiedNameAST *ast)
|
bool CheckUndefinedSymbols::visit(QualifiedNameAST *ast)
|
||||||
{
|
{
|
||||||
if (ast->name) {
|
if (ast->name) {
|
||||||
Scope *scope = CollectTypes::findScope(tokenAt(ast->firstToken()).offset, _scopes); // ### move
|
Scope *scope = findScope(ast);
|
||||||
if (! scope)
|
|
||||||
scope = _context.thisDocument()->globalSymbols();
|
|
||||||
|
|
||||||
ClassOrNamespace *b = 0;
|
ClassOrNamespace *b = 0;
|
||||||
if (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list) {
|
if (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list) {
|
||||||
NestedNameSpecifierAST *nested_name_specifier = it->value;
|
NestedNameSpecifierAST *nested_name_specifier = it->value;
|
||||||
NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name; // ### remove shadowing
|
NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name; // ### remove shadowing
|
||||||
|
|
||||||
|
if (class_or_namespace_name)
|
||||||
|
if (TemplateIdAST *template_id = class_or_namespace_name->asTemplateId())
|
||||||
|
accept(template_id->template_argument_list);
|
||||||
|
|
||||||
const Name *name = class_or_namespace_name->name;
|
const Name *name = class_or_namespace_name->name;
|
||||||
b = _context.lookupType(name, scope);
|
b = _context.lookupType(name, scope);
|
||||||
addTypeUsage(b, class_or_namespace_name);
|
addTypeUsage(b, class_or_namespace_name);
|
||||||
@@ -390,6 +395,9 @@ bool CheckUndefinedSymbols::visit(QualifiedNameAST *ast)
|
|||||||
NestedNameSpecifierAST *nested_name_specifier = it->value;
|
NestedNameSpecifierAST *nested_name_specifier = it->value;
|
||||||
|
|
||||||
if (NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name) {
|
if (NameAST *class_or_namespace_name = nested_name_specifier->class_or_namespace_name) {
|
||||||
|
if (TemplateIdAST *template_id = class_or_namespace_name->asTemplateId())
|
||||||
|
accept(template_id->template_argument_list);
|
||||||
|
|
||||||
b = b->findType(class_or_namespace_name->name);
|
b = b->findType(class_or_namespace_name->name);
|
||||||
addTypeUsage(b, class_or_namespace_name);
|
addTypeUsage(b, class_or_namespace_name);
|
||||||
}
|
}
|
||||||
@@ -403,17 +411,53 @@ bool CheckUndefinedSymbols::visit(QualifiedNameAST *ast)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CheckUndefinedSymbols::visit(TypenameTypeParameterAST *ast)
|
||||||
|
{
|
||||||
|
if (ast->name) {
|
||||||
|
if (const Identifier *templId = ast->name->name->identifier()) {
|
||||||
|
const QByteArray id = QByteArray::fromRawData(templId->chars(), templId->size());
|
||||||
|
if (_potentialTypes.contains(id)) {
|
||||||
|
Scope *scope = findScope(_templateDeclarationStack.back());
|
||||||
|
const QList<Symbol *> candidates = _context.lookup(ast->name->name, scope);
|
||||||
|
addTypeUsage(candidates, ast->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckUndefinedSymbols::visit(TemplateTypeParameterAST *ast)
|
||||||
|
{
|
||||||
|
checkName(ast->name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckUndefinedSymbols::visit(TemplateDeclarationAST *ast)
|
||||||
|
{
|
||||||
|
_templateDeclarationStack.append(ast);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckUndefinedSymbols::endVisit(TemplateDeclarationAST *)
|
||||||
|
{
|
||||||
|
_templateDeclarationStack.takeFirst();
|
||||||
|
}
|
||||||
|
|
||||||
void CheckUndefinedSymbols::addTypeUsage(ClassOrNamespace *b, NameAST *ast)
|
void CheckUndefinedSymbols::addTypeUsage(ClassOrNamespace *b, NameAST *ast)
|
||||||
{
|
{
|
||||||
if (! b)
|
if (! b)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const Token &tok = tokenAt(ast->firstToken());
|
unsigned startToken = ast->firstToken();
|
||||||
|
if (DestructorNameAST *dtor = ast->asDestructorName())
|
||||||
|
startToken = dtor->identifier_token;
|
||||||
|
|
||||||
|
const Token &tok = tokenAt(startToken);
|
||||||
if (tok.generated())
|
if (tok.generated())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned line, column;
|
unsigned line, column;
|
||||||
getTokenStartPosition(ast->firstToken(), &line, &column);
|
getTokenStartPosition(startToken, &line, &column);
|
||||||
const unsigned length = tok.length();
|
const unsigned length = tok.length();
|
||||||
Use use(line, column, length);
|
Use use(line, column, length);
|
||||||
_typeUsages.append(use);
|
_typeUsages.append(use);
|
||||||
@@ -422,12 +466,16 @@ void CheckUndefinedSymbols::addTypeUsage(ClassOrNamespace *b, NameAST *ast)
|
|||||||
|
|
||||||
void CheckUndefinedSymbols::addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast)
|
void CheckUndefinedSymbols::addTypeUsage(const QList<Symbol *> &candidates, NameAST *ast)
|
||||||
{
|
{
|
||||||
const Token &tok = tokenAt(ast->firstToken());
|
unsigned startToken = ast->firstToken();
|
||||||
|
if (DestructorNameAST *dtor = ast->asDestructorName())
|
||||||
|
startToken = dtor->identifier_token;
|
||||||
|
|
||||||
|
const Token &tok = tokenAt(startToken);
|
||||||
if (tok.generated())
|
if (tok.generated())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned line, column;
|
unsigned line, column;
|
||||||
getTokenStartPosition(ast->firstToken(), &line, &column);
|
getTokenStartPosition(startToken, &line, &column);
|
||||||
const unsigned length = tok.length();
|
const unsigned length = tok.length();
|
||||||
|
|
||||||
foreach (Symbol *c, candidates) {
|
foreach (Symbol *c, candidates) {
|
||||||
@@ -450,3 +498,34 @@ QList<CheckUndefinedSymbols::Use> CheckUndefinedSymbols::typeUsages() const
|
|||||||
{
|
{
|
||||||
return _typeUsages;
|
return _typeUsages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned CheckUndefinedSymbols::startOfTemplateDeclaration(TemplateDeclarationAST *ast) const
|
||||||
|
{
|
||||||
|
if (ast->declaration) {
|
||||||
|
if (TemplateDeclarationAST *templ = ast->declaration->asTemplateDeclaration())
|
||||||
|
return startOfTemplateDeclaration(templ);
|
||||||
|
|
||||||
|
return ast->declaration->firstToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ast->firstToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope *CheckUndefinedSymbols::findScope(AST *ast) const
|
||||||
|
{
|
||||||
|
Scope *scope = 0;
|
||||||
|
|
||||||
|
if (ast) {
|
||||||
|
unsigned startToken = ast->firstToken();
|
||||||
|
if (TemplateDeclarationAST *templ = ast->asTemplateDeclaration())
|
||||||
|
startToken = startOfTemplateDeclaration(templ);
|
||||||
|
|
||||||
|
const unsigned tokenOffset = tokenAt(startToken).offset;
|
||||||
|
scope = CollectTypes::findScope(tokenOffset, _scopes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! scope)
|
||||||
|
scope = _context.thisDocument()->globalSymbols();
|
||||||
|
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
@@ -58,6 +58,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
using ASTVisitor::visit;
|
using ASTVisitor::visit;
|
||||||
|
using ASTVisitor::endVisit;
|
||||||
|
|
||||||
bool warning(unsigned line, unsigned column, const QString &text, unsigned length = 0);
|
bool warning(unsigned line, unsigned column, const QString &text, unsigned length = 0);
|
||||||
bool warning(AST *ast, const QString &text);
|
bool warning(AST *ast, const QString &text);
|
||||||
@@ -77,6 +78,15 @@ protected:
|
|||||||
virtual bool visit(QualifiedNameAST *ast);
|
virtual bool visit(QualifiedNameAST *ast);
|
||||||
virtual bool visit(TemplateIdAST *ast);
|
virtual bool visit(TemplateIdAST *ast);
|
||||||
|
|
||||||
|
virtual bool visit(TemplateDeclarationAST *ast);
|
||||||
|
virtual void endVisit(TemplateDeclarationAST *ast);
|
||||||
|
|
||||||
|
virtual bool visit(TypenameTypeParameterAST *ast);
|
||||||
|
virtual bool visit(TemplateTypeParameterAST *ast);
|
||||||
|
|
||||||
|
unsigned startOfTemplateDeclaration(TemplateDeclarationAST *ast) const;
|
||||||
|
Scope *findScope(AST *ast) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LookupContext _context;
|
LookupContext _context;
|
||||||
QString _fileName;
|
QString _fileName;
|
||||||
@@ -84,6 +94,7 @@ private:
|
|||||||
QSet<QByteArray> _potentialTypes;
|
QSet<QByteArray> _potentialTypes;
|
||||||
QList<ScopedSymbol *> _scopes;
|
QList<ScopedSymbol *> _scopes;
|
||||||
QList<Use> _typeUsages;
|
QList<Use> _typeUsages;
|
||||||
|
QList<TemplateDeclarationAST *> _templateDeclarationStack;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end of namespace CPlusPlus
|
} // end of namespace CPlusPlus
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "FindUsages.h"
|
#include "FindUsages.h"
|
||||||
|
#include "Overview.h"
|
||||||
|
|
||||||
#include <Control.h>
|
#include <Control.h>
|
||||||
#include <Literals.h>
|
#include <Literals.h>
|
||||||
@@ -436,3 +437,54 @@ bool FindUsages::visit(QtPropertyDeclarationAST *)
|
|||||||
|
|
||||||
void FindUsages::endVisit(QtPropertyDeclarationAST *)
|
void FindUsages::endVisit(QtPropertyDeclarationAST *)
|
||||||
{ _inQProperty = false; }
|
{ _inQProperty = false; }
|
||||||
|
|
||||||
|
bool FindUsages::visit(TemplateDeclarationAST *ast)
|
||||||
|
{
|
||||||
|
_templateDeclarationStack.append(ast);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindUsages::endVisit(TemplateDeclarationAST *)
|
||||||
|
{
|
||||||
|
_templateDeclarationStack.takeFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindUsages::visit(TypenameTypeParameterAST *ast)
|
||||||
|
{
|
||||||
|
if (NameAST *name = ast->name) {
|
||||||
|
const Identifier *id = name->name->identifier();
|
||||||
|
if (id == _id) {
|
||||||
|
unsigned start = startOfTemplateDeclaration(_templateDeclarationStack.back());
|
||||||
|
const QList<Symbol *> candidates = _context.lookup(name->name, scopeAt(start));
|
||||||
|
reportResult(ast->name->firstToken(), candidates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
accept(ast->type_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindUsages::visit(TemplateTypeParameterAST *ast)
|
||||||
|
{
|
||||||
|
if (NameAST *name = ast->name) {
|
||||||
|
const Identifier *id = name->name->identifier();
|
||||||
|
if (id == _id) {
|
||||||
|
unsigned start = startOfTemplateDeclaration(_templateDeclarationStack.back());
|
||||||
|
const QList<Symbol *> candidates = _context.lookup(name->name, scopeAt(start));
|
||||||
|
reportResult(ast->name->firstToken(), candidates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
accept(ast->type_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned FindUsages::startOfTemplateDeclaration(TemplateDeclarationAST *ast) const
|
||||||
|
{
|
||||||
|
if (ast->declaration) {
|
||||||
|
if (TemplateDeclarationAST *templ = ast->declaration->asTemplateDeclaration())
|
||||||
|
return startOfTemplateDeclaration(templ);
|
||||||
|
|
||||||
|
return ast->declaration->firstToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ast->firstToken();
|
||||||
|
}
|
||||||
|
@@ -99,6 +99,14 @@ protected:
|
|||||||
virtual bool visit(QtPropertyDeclarationAST *);
|
virtual bool visit(QtPropertyDeclarationAST *);
|
||||||
virtual void endVisit(QtPropertyDeclarationAST *);
|
virtual void endVisit(QtPropertyDeclarationAST *);
|
||||||
|
|
||||||
|
virtual bool visit(TemplateDeclarationAST *ast);
|
||||||
|
virtual void endVisit(TemplateDeclarationAST *ast);
|
||||||
|
|
||||||
|
virtual bool visit(TypenameTypeParameterAST *ast);
|
||||||
|
virtual bool visit(TemplateTypeParameterAST *ast);
|
||||||
|
|
||||||
|
unsigned startOfTemplateDeclaration(TemplateDeclarationAST *ast) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Identifier *_id;
|
const Identifier *_id;
|
||||||
Symbol *_declSymbol;
|
Symbol *_declSymbol;
|
||||||
@@ -110,6 +118,7 @@ private:
|
|||||||
Semantic _sem;
|
Semantic _sem;
|
||||||
QList<PostfixExpressionAST *> _postfixExpressionStack;
|
QList<PostfixExpressionAST *> _postfixExpressionStack;
|
||||||
QList<QualifiedNameAST *> _qualifiedNameStack;
|
QList<QualifiedNameAST *> _qualifiedNameStack;
|
||||||
|
QList<TemplateDeclarationAST *> _templateDeclarationStack;
|
||||||
QList<int> _references;
|
QList<int> _references;
|
||||||
QList<Usage> _usages;
|
QList<Usage> _usages;
|
||||||
int _inSimpleDeclaration;
|
int _inSimpleDeclaration;
|
||||||
|
Reference in New Issue
Block a user