forked from qt-creator/qt-creator
Initial work on smart highlight of local symbols. For-statements and symbols genarated from a macro expansion are not yet highlighted.
This commit is contained in:
@@ -71,6 +71,7 @@
|
|||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QTime>
|
#include <QtCore/QTime>
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
|
#include <QtCore/QStack>
|
||||||
#include <QtGui/QAction>
|
#include <QtGui/QAction>
|
||||||
#include <QtGui/QHeaderView>
|
#include <QtGui/QHeaderView>
|
||||||
#include <QtGui/QLayout>
|
#include <QtGui/QLayout>
|
||||||
@@ -109,6 +110,217 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FindLocals: protected ASTVisitor
|
||||||
|
{
|
||||||
|
Scope *_functionScope;
|
||||||
|
|
||||||
|
class FindScope: protected SymbolVisitor
|
||||||
|
{
|
||||||
|
TranslationUnit *_unit;
|
||||||
|
Scope *_scope;
|
||||||
|
unsigned _line;
|
||||||
|
unsigned _column;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Scope *operator()(unsigned line, unsigned column,
|
||||||
|
Symbol *root, TranslationUnit *unit)
|
||||||
|
{
|
||||||
|
_unit = unit;
|
||||||
|
_scope = 0;
|
||||||
|
_line = line;
|
||||||
|
_column = column;
|
||||||
|
accept(root);
|
||||||
|
return _scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
using SymbolVisitor::visit;
|
||||||
|
|
||||||
|
virtual bool preVisit(Symbol *)
|
||||||
|
{ return ! _scope; }
|
||||||
|
|
||||||
|
virtual bool visit(Block *block)
|
||||||
|
{ return processScope(block->members()); }
|
||||||
|
|
||||||
|
virtual bool visit(Function *function)
|
||||||
|
{ return processScope(function->members()); }
|
||||||
|
|
||||||
|
bool processScope(Scope *scope)
|
||||||
|
{
|
||||||
|
if (_scope || ! scope)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < scope->symbolCount(); ++i) {
|
||||||
|
accept(scope->symbolAt(i));
|
||||||
|
|
||||||
|
if (_scope)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned startOffset = scope->owner()->startOffset();
|
||||||
|
unsigned endOffset = scope->owner()->endOffset();
|
||||||
|
|
||||||
|
unsigned startLine, startColumn;
|
||||||
|
unsigned endLine, endColumn;
|
||||||
|
|
||||||
|
_unit->getPosition(startOffset, &startLine, &startColumn);
|
||||||
|
_unit->getPosition(endOffset, &endLine, &endColumn);
|
||||||
|
|
||||||
|
if (_line > startLine || (_line == startLine && _column >= startColumn)) {
|
||||||
|
if (_line < endLine || (_line == endLine && _column < endColumn)) {
|
||||||
|
_scope = scope;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
FindLocals(Control *control)
|
||||||
|
: ASTVisitor(control)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
struct Use {
|
||||||
|
SimpleNameAST *name;
|
||||||
|
unsigned line;
|
||||||
|
unsigned column;
|
||||||
|
unsigned length;
|
||||||
|
|
||||||
|
Use(){}
|
||||||
|
|
||||||
|
Use(SimpleNameAST *name, unsigned line, unsigned column, unsigned length)
|
||||||
|
: name(name), line(line), column(column), length(length) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef QHash<Symbol *, QList<Use> > UseMap;
|
||||||
|
typedef QHashIterator<Symbol *, QList<Use> > UseIterator;
|
||||||
|
|
||||||
|
UseMap uses; // ### private
|
||||||
|
|
||||||
|
UseMap operator()(FunctionDefinitionAST *ast)
|
||||||
|
{
|
||||||
|
uses.clear();
|
||||||
|
if (ast && ast->symbol) {
|
||||||
|
_functionScope = ast->symbol->members();
|
||||||
|
accept(ast);
|
||||||
|
}
|
||||||
|
return uses;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using ASTVisitor::visit;
|
||||||
|
|
||||||
|
bool findMember(Scope *scope, SimpleNameAST *ast, unsigned line, unsigned column)
|
||||||
|
{
|
||||||
|
Identifier *id = identifier(ast->identifier_token);
|
||||||
|
|
||||||
|
if (scope) {
|
||||||
|
for (Symbol *member = scope->lookat(id); member; member = member->next()) {
|
||||||
|
if (member->identifier() != id)
|
||||||
|
continue;
|
||||||
|
else if (member->line() < line || (member->line() == line && (member->isGenerated() || member->column() >= column))) {
|
||||||
|
//qDebug() << "*** found member:" << member->line() << member->column() << member->name()->identifier()->chars();
|
||||||
|
uses[member].append(Use(ast, line, column, id->size()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool visit(SimpleNameAST *ast)
|
||||||
|
{
|
||||||
|
unsigned line, column;
|
||||||
|
getTokenStartPosition(ast->firstToken(), &line, &column);
|
||||||
|
|
||||||
|
FindScope findScope;
|
||||||
|
|
||||||
|
Scope *scope = findScope(line, column,
|
||||||
|
_functionScope->owner(),
|
||||||
|
translationUnit());
|
||||||
|
|
||||||
|
while (scope) {
|
||||||
|
if (scope->isFunctionScope()) {
|
||||||
|
Function *fun = scope->owner()->asFunction();
|
||||||
|
if (findMember(fun->members(), ast, line, column))
|
||||||
|
return false;
|
||||||
|
else if (findMember(fun->arguments(), ast, line, column))
|
||||||
|
return false;
|
||||||
|
} else if (scope->isBlockScope()) {
|
||||||
|
if (findMember(scope, ast, line, column))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
scope = scope->enclosingScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
qDebug() << "symbol:" << id->chars() << "at pos:" << line << column
|
||||||
|
<< "is not defined";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool visit(QualifiedNameAST *)
|
||||||
|
{
|
||||||
|
// ### visit the template arguments.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool visit(PostfixExpressionAST *ast)
|
||||||
|
{
|
||||||
|
accept(ast->base_expression);
|
||||||
|
for (PostfixAST *it = ast->postfix_expressions; it; it = it->next) {
|
||||||
|
if (it->asMemberAccess() != 0)
|
||||||
|
continue; // skip members
|
||||||
|
accept(it);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool visit(NewExpressionAST *ast)
|
||||||
|
{
|
||||||
|
accept(ast->new_placement);
|
||||||
|
accept(ast->new_initializer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool visit(ElaboratedTypeSpecifierAST *)
|
||||||
|
{
|
||||||
|
// ### template args
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool visit(ClassSpecifierAST *)
|
||||||
|
{
|
||||||
|
// ### template args
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool visit(EnumSpecifierAST *)
|
||||||
|
{
|
||||||
|
// ### template args
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool visit(UsingDirectiveAST *)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool visit(UsingAST *ast)
|
||||||
|
{
|
||||||
|
accept(ast->name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class FunctionDefinitionUnderCursor: protected ASTVisitor
|
class FunctionDefinitionUnderCursor: protected ASTVisitor
|
||||||
{
|
{
|
||||||
QTextCursor _textCursor;
|
QTextCursor _textCursor;
|
||||||
@@ -620,6 +832,7 @@ void CPPEditor::simplifyDeclarations()
|
|||||||
const QString fileName = file()->fileName();
|
const QString fileName = file()->fileName();
|
||||||
const QByteArray preprocessedCode = snapshot.preprocessedCode(plainText, fileName);
|
const QByteArray preprocessedCode = snapshot.preprocessedCode(plainText, fileName);
|
||||||
Document::Ptr doc = snapshot.documentFromSource(preprocessedCode, fileName);
|
Document::Ptr doc = snapshot.documentFromSource(preprocessedCode, fileName);
|
||||||
|
doc->check();
|
||||||
|
|
||||||
SimplifyDeclarations simplify(this, doc);
|
SimplifyDeclarations simplify(this, doc);
|
||||||
simplify(textCursor());
|
simplify(textCursor());
|
||||||
@@ -692,6 +905,7 @@ void CPPEditor::updateMethodBoxIndexNow()
|
|||||||
const Snapshot snapshot = m_modelManager->snapshot();
|
const Snapshot snapshot = m_modelManager->snapshot();
|
||||||
const QByteArray preprocessedCode = snapshot.preprocessedCode(toPlainText(), file()->fileName());
|
const QByteArray preprocessedCode = snapshot.preprocessedCode(toPlainText(), file()->fileName());
|
||||||
Document::Ptr doc = snapshot.documentFromSource(preprocessedCode, file()->fileName());
|
Document::Ptr doc = snapshot.documentFromSource(preprocessedCode, file()->fileName());
|
||||||
|
doc->check();
|
||||||
Control *control = doc->control();
|
Control *control = doc->control();
|
||||||
TranslationUnit *translationUnit = doc->translationUnit();
|
TranslationUnit *translationUnit = doc->translationUnit();
|
||||||
AST *ast = translationUnit->ast();
|
AST *ast = translationUnit->ast();
|
||||||
@@ -699,33 +913,56 @@ void CPPEditor::updateMethodBoxIndexNow()
|
|||||||
FunctionDefinitionUnderCursor functionDefinitionUnderCursor(control);
|
FunctionDefinitionUnderCursor functionDefinitionUnderCursor(control);
|
||||||
FunctionDefinitionAST *currentFunctionDefinition = functionDefinitionUnderCursor(ast, textCursor());
|
FunctionDefinitionAST *currentFunctionDefinition = functionDefinitionUnderCursor(ast, textCursor());
|
||||||
|
|
||||||
|
|
||||||
QTextCharFormat format;
|
QTextCharFormat format;
|
||||||
format.setUnderlineColor(Qt::darkGray);
|
format.setUnderlineColor(Qt::darkGray);
|
||||||
format.setUnderlineStyle(QTextCharFormat::DashUnderline);
|
format.setUnderlineStyle(QTextCharFormat::DashUnderline);
|
||||||
ProcessDeclarators processDeclarators(control);
|
FindLocals findLocals(control);
|
||||||
const QList<DeclaratorIdAST *> declarators = processDeclarators(currentFunctionDefinition);
|
const FindLocals::UseMap useMap = findLocals(currentFunctionDefinition);
|
||||||
foreach (DeclaratorIdAST *declarator, declarators) {
|
FindLocals::UseIterator it(useMap);
|
||||||
bool generated = false;
|
while (it.hasNext()) {
|
||||||
for (unsigned tk = declarator->firstToken(), end = declarator->lastToken(); tk != end; ++tk) {
|
it.next();
|
||||||
if (translationUnit->tokenAt(tk).generated) {
|
const QList<FindLocals::Use> &uses = it.value();
|
||||||
generated = true;
|
|
||||||
|
bool good = false;
|
||||||
|
foreach (const FindLocals::Use &use, uses) {
|
||||||
|
unsigned l = line;
|
||||||
|
unsigned c = column + 1; // convertCursorPosition() returns a 0-based column number.
|
||||||
|
if (l == use.line && c >= use.column && c <= (use.column + use.length)) {
|
||||||
|
good = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (generated)
|
|
||||||
|
if (! good)
|
||||||
continue;
|
continue;
|
||||||
unsigned startLine, startColumn;
|
|
||||||
unsigned endLine, endColumn;
|
foreach (const FindLocals::Use &use, uses) {
|
||||||
translationUnit->getTokenStartPosition(declarator->firstToken(), &startLine, &startColumn);
|
SimpleNameAST *name = use.name;
|
||||||
translationUnit->getTokenEndPosition(declarator->lastToken() - 1, &endLine, &endColumn);
|
bool generated = false;
|
||||||
QTextEdit::ExtraSelection sel;
|
for (unsigned tk = name->firstToken(), end = name->lastToken(); tk != end; ++tk) {
|
||||||
sel.cursor = textCursor();
|
if (translationUnit->tokenAt(tk).generated) {
|
||||||
sel.cursor.setPosition(document()->findBlockByNumber(startLine - 1).position() + startColumn - 1);
|
generated = true;
|
||||||
sel.cursor.setPosition(document()->findBlockByLineNumber(endLine - 1).position() + endColumn - 1,
|
break;
|
||||||
QTextCursor::KeepAnchor);
|
}
|
||||||
sel.format = format;
|
}
|
||||||
selections.append(sel);
|
if (generated)
|
||||||
|
continue;
|
||||||
|
unsigned startLine, startColumn;
|
||||||
|
unsigned endLine, endColumn;
|
||||||
|
translationUnit->getTokenStartPosition(name->firstToken(), &startLine, &startColumn);
|
||||||
|
translationUnit->getTokenEndPosition(name->lastToken() - 1, &endLine, &endColumn);
|
||||||
|
QTextEdit::ExtraSelection sel;
|
||||||
|
sel.cursor = textCursor();
|
||||||
|
sel.cursor.setPosition(document()->findBlockByNumber(startLine - 1).position() + startColumn - 1);
|
||||||
|
sel.cursor.setPosition(document()->findBlockByLineNumber(endLine - 1).position() + endColumn - 1,
|
||||||
|
QTextCursor::KeepAnchor);
|
||||||
|
sel.format = format;
|
||||||
|
selections.append(sel);
|
||||||
|
}
|
||||||
|
break; // done.
|
||||||
}
|
}
|
||||||
|
|
||||||
setExtraSelections(CodeSemanticsSelection, selections);
|
setExtraSelections(CodeSemanticsSelection, selections);
|
||||||
|
|
||||||
#ifdef QTCREATOR_WITH_ADVANCED_HIGHLIGHTER
|
#ifdef QTCREATOR_WITH_ADVANCED_HIGHLIGHTER
|
||||||
|
|||||||
@@ -122,6 +122,18 @@ void CheckDeclaration::checkFunctionArguments(Function *fun)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned CheckDeclaration::locationOfDeclaratorId(DeclaratorAST *declarator) const
|
||||||
|
{
|
||||||
|
if (declarator && declarator->core_declarator) {
|
||||||
|
if (DeclaratorIdAST *declaratorId = declarator->core_declarator->asDeclaratorId())
|
||||||
|
return declaratorId->firstToken();
|
||||||
|
else if (NestedDeclaratorAST *nested = declarator->core_declarator->asNestedDeclarator())
|
||||||
|
return locationOfDeclaratorId(nested->declarator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
|
bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
|
||||||
{
|
{
|
||||||
FullySpecifiedType ty = semantic()->check(ast->decl_specifier_seq, _scope);
|
FullySpecifiedType ty = semantic()->check(ast->decl_specifier_seq, _scope);
|
||||||
@@ -164,11 +176,13 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
|
|||||||
FullySpecifiedType declTy = semantic()->check(it->declarator, qualTy,
|
FullySpecifiedType declTy = semantic()->check(it->declarator, qualTy,
|
||||||
_scope, &name);
|
_scope, &name);
|
||||||
|
|
||||||
unsigned location = 0;
|
unsigned location = locationOfDeclaratorId(it->declarator);
|
||||||
if (it->declarator)
|
if (! location) {
|
||||||
location = it->declarator->firstToken();
|
if (it->declarator)
|
||||||
else
|
location = it->declarator->firstToken();
|
||||||
location = ast->firstToken();
|
else
|
||||||
|
location = ast->firstToken();
|
||||||
|
}
|
||||||
|
|
||||||
Function *fun = 0;
|
Function *fun = 0;
|
||||||
if (declTy && 0 != (fun = declTy->asFunctionType())) {
|
if (declTy && 0 != (fun = declTy->asFunctionType())) {
|
||||||
@@ -355,10 +369,13 @@ bool CheckDeclaration::visit(NamespaceAliasDefinitionAST *)
|
|||||||
|
|
||||||
bool CheckDeclaration::visit(ParameterDeclarationAST *ast)
|
bool CheckDeclaration::visit(ParameterDeclarationAST *ast)
|
||||||
{
|
{
|
||||||
unsigned sourceLocation = 0;
|
unsigned sourceLocation = locationOfDeclaratorId(ast->declarator);
|
||||||
|
if (! sourceLocation) {
|
||||||
if (ast->declarator)
|
if (ast->declarator)
|
||||||
sourceLocation = ast->declarator->firstToken();
|
sourceLocation = ast->declarator->firstToken();
|
||||||
|
else
|
||||||
|
sourceLocation = ast->firstToken();
|
||||||
|
}
|
||||||
|
|
||||||
Name *argName = 0;
|
Name *argName = 0;
|
||||||
FullySpecifiedType ty = semantic()->check(ast->type_specifier, _scope);
|
FullySpecifiedType ty = semantic()->check(ast->type_specifier, _scope);
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ protected:
|
|||||||
|
|
||||||
using ASTVisitor::visit;
|
using ASTVisitor::visit;
|
||||||
|
|
||||||
|
unsigned locationOfDeclaratorId(DeclaratorAST *declarator) const;
|
||||||
|
|
||||||
virtual bool visit(SimpleDeclarationAST *ast);
|
virtual bool visit(SimpleDeclarationAST *ast);
|
||||||
virtual bool visit(EmptyDeclarationAST *ast);
|
virtual bool visit(EmptyDeclarationAST *ast);
|
||||||
virtual bool visit(AccessDeclarationAST *ast);
|
virtual bool visit(AccessDeclarationAST *ast);
|
||||||
|
|||||||
@@ -144,6 +144,8 @@ bool CheckStatement::visit(ExpressionStatementAST *ast)
|
|||||||
bool CheckStatement::visit(ForStatementAST *ast)
|
bool CheckStatement::visit(ForStatementAST *ast)
|
||||||
{
|
{
|
||||||
Block *block = control()->newBlock(ast->for_token);
|
Block *block = control()->newBlock(ast->for_token);
|
||||||
|
block->setStartOffset(tokenAt(ast->firstToken()).offset);
|
||||||
|
block->setEndOffset(tokenAt(ast->lastToken()).offset);
|
||||||
ast->symbol = block;
|
ast->symbol = block;
|
||||||
_scope->enterSymbol(block);
|
_scope->enterSymbol(block);
|
||||||
Scope *previousScope = switchScope(block->members());
|
Scope *previousScope = switchScope(block->members());
|
||||||
@@ -158,6 +160,8 @@ bool CheckStatement::visit(ForStatementAST *ast)
|
|||||||
bool CheckStatement::visit(IfStatementAST *ast)
|
bool CheckStatement::visit(IfStatementAST *ast)
|
||||||
{
|
{
|
||||||
Block *block = control()->newBlock(ast->if_token);
|
Block *block = control()->newBlock(ast->if_token);
|
||||||
|
block->setStartOffset(tokenAt(ast->firstToken()).offset);
|
||||||
|
block->setEndOffset(tokenAt(ast->lastToken()).offset);
|
||||||
ast->symbol = block;
|
ast->symbol = block;
|
||||||
_scope->enterSymbol(block);
|
_scope->enterSymbol(block);
|
||||||
Scope *previousScope = switchScope(block->members());
|
Scope *previousScope = switchScope(block->members());
|
||||||
@@ -198,6 +202,8 @@ bool CheckStatement::visit(ReturnStatementAST *ast)
|
|||||||
bool CheckStatement::visit(SwitchStatementAST *ast)
|
bool CheckStatement::visit(SwitchStatementAST *ast)
|
||||||
{
|
{
|
||||||
Block *block = control()->newBlock(ast->switch_token);
|
Block *block = control()->newBlock(ast->switch_token);
|
||||||
|
block->setStartOffset(tokenAt(ast->firstToken()).offset);
|
||||||
|
block->setEndOffset(tokenAt(ast->lastToken()).offset);
|
||||||
ast->symbol = block;
|
ast->symbol = block;
|
||||||
_scope->enterSymbol(block);
|
_scope->enterSymbol(block);
|
||||||
Scope *previousScope = switchScope(block->members());
|
Scope *previousScope = switchScope(block->members());
|
||||||
@@ -219,6 +225,8 @@ bool CheckStatement::visit(TryBlockStatementAST *ast)
|
|||||||
bool CheckStatement::visit(CatchClauseAST *ast)
|
bool CheckStatement::visit(CatchClauseAST *ast)
|
||||||
{
|
{
|
||||||
Block *block = control()->newBlock(ast->catch_token);
|
Block *block = control()->newBlock(ast->catch_token);
|
||||||
|
block->setStartOffset(tokenAt(ast->firstToken()).offset);
|
||||||
|
block->setEndOffset(tokenAt(ast->lastToken()).offset);
|
||||||
ast->symbol = block;
|
ast->symbol = block;
|
||||||
_scope->enterSymbol(block);
|
_scope->enterSymbol(block);
|
||||||
Scope *previousScope = switchScope(block->members());
|
Scope *previousScope = switchScope(block->members());
|
||||||
@@ -231,6 +239,8 @@ bool CheckStatement::visit(CatchClauseAST *ast)
|
|||||||
bool CheckStatement::visit(WhileStatementAST *ast)
|
bool CheckStatement::visit(WhileStatementAST *ast)
|
||||||
{
|
{
|
||||||
Block *block = control()->newBlock(ast->while_token);
|
Block *block = control()->newBlock(ast->while_token);
|
||||||
|
block->setStartOffset(tokenAt(ast->firstToken()).offset);
|
||||||
|
block->setEndOffset(tokenAt(ast->lastToken()).offset);
|
||||||
ast->symbol = block;
|
ast->symbol = block;
|
||||||
_scope->enterSymbol(block);
|
_scope->enterSymbol(block);
|
||||||
Scope *previousScope = switchScope(block->members());
|
Scope *previousScope = switchScope(block->members());
|
||||||
|
|||||||
@@ -328,7 +328,13 @@ FullySpecifiedType Block::type() const
|
|||||||
{ return FullySpecifiedType(); }
|
{ return FullySpecifiedType(); }
|
||||||
|
|
||||||
void Block::visitSymbol0(SymbolVisitor *visitor)
|
void Block::visitSymbol0(SymbolVisitor *visitor)
|
||||||
{ visitor->visit(this); }
|
{
|
||||||
|
if (visitor->visit(this)) {
|
||||||
|
for (unsigned i = 0; i < memberCount(); ++i) {
|
||||||
|
visitSymbol(memberAt(i), visitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Enum::Enum(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
|
Enum::Enum(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name)
|
||||||
: ScopedSymbol(translationUnit, sourceLocation, name)
|
: ScopedSymbol(translationUnit, sourceLocation, name)
|
||||||
|
|||||||
Reference in New Issue
Block a user