static void debugCppSymbolRecursion(QTextStream &str, const Overview &o, const Symbol &s, bool doRecurse = true, int recursion = 0) { for (int i = 0; i < recursion; i++) str << " "; str << "Symbol: " << o.prettyName(s.name()) << " at line " << s.line(); if (s.isFunction()) str << " function"; if (s.isClass()) str << " class"; if (s.isDeclaration()) str << " declaration"; if (s.isBlock()) str << " block"; if (doRecurse && s.isScope()) { const Scope *scoped = s.asScope(); const int size = scoped->memberCount(); str << " scoped symbol of " << size << '\n'; for (int m = 0; m < size; m++) debugCppSymbolRecursion(str, o, *scoped->memberAt(m), true, recursion + 1); } else { str << '\n'; } }
int OverviewModel::rowCount(const QModelIndex &parent) const { if (hasDocument()) { if (!parent.isValid()) { return globalSymbolCount()+1; // account for no symbol item } else { if (!parent.parent().isValid() && parent.row() == 0) // account for no symbol item return 0; Symbol *parentSymbol = static_cast<Symbol *>(parent.internalPointer()); Q_ASSERT(parentSymbol); if (Template *t = parentSymbol->asTemplate()) if (Symbol *templateParentSymbol = t->declaration()) parentSymbol = templateParentSymbol; if (Scope *parentScope = parentSymbol->asScope()) { if (!parentScope->isFunction() && !parentScope->isObjCMethod()) return parentScope->memberCount(); } return 0; } } if (!parent.isValid()) return 1; // account for no symbol item return 0; }
QModelIndex OverviewModel::index(int row, int column, const QModelIndex &parent) const { if (!parent.isValid()) { if (row == 0) // account for no symbol item return createIndex(row, column); Symbol *symbol = globalSymbolAt(row-1); // account for no symbol item return createIndex(row, column, symbol); } else { Symbol *parentSymbol = static_cast<Symbol *>(parent.internalPointer()); Q_ASSERT(parentSymbol); Scope *scope = parentSymbol->asScope(); Q_ASSERT(scope != 0); return createIndex(row, 0, scope->memberAt(row)); } }
/*! * Extract the function name including scope at the given position. * * Note that a function (scope) starts at the name of that function, not at the return type. The * implication is that this function will return an empty string when the line/column is on the * return type. * * \param line the line number, starting with line 1 * \param column the column number, starting with column 1 * \param lineOpeningDeclaratorParenthesis optional output parameter, the line of the opening parenthesis of the declarator starting with 1 * \param lineClosingBrace optional output parameter, the line of the closing brace starting with 1 */ QString Document::functionAt(int line, int column, int *lineOpeningDeclaratorParenthesis, int *lineClosingBrace) const { if (line < 1 || column < 1) return QString(); Symbol *symbol = lastVisibleSymbolAt(line, column); if (!symbol) return QString(); // Find the enclosing function scope (which might be several levels up, or we might be standing // on it) Scope *scope = symbol->asScope(); if (!scope) scope = symbol->enclosingScope(); while (scope && !scope->isFunction() ) scope = scope->enclosingScope(); if (!scope) return QString(); // We found the function scope if (lineOpeningDeclaratorParenthesis) { unsigned line; translationUnit()->getPosition(scope->startOffset(), &line); *lineOpeningDeclaratorParenthesis = static_cast<int>(line); } if (lineClosingBrace) { unsigned line; translationUnit()->getPosition(scope->endOffset(), &line); *lineClosingBrace = static_cast<int>(line); } const QList<const Name *> fullyQualifiedName = LookupContext::fullyQualifiedName(scope); return Overview().prettyName(fullyQualifiedName); }
/*! Handle declaration in if, while and for statements */ void PointerDeclarationFormatter::processIfWhileForStatement(ExpressionAST *expression, Symbol *statementSymbol) { CHECK_R(expression, "No expression"); CHECK_R(statementSymbol, "No symbol"); ConditionAST *condition = expression->asCondition(); CHECK_R(condition, "No condition"); DeclaratorAST *declarator = condition->declarator; CHECK_R(declarator, "No declarator"); CHECK_R(declarator->ptr_operator_list, "No Pointer or references"); CHECK_R(declarator->equal_token, "No equal token"); Block *block = statementSymbol->asBlock(); CHECK_R(block, "No block"); CHECK_R(block->memberCount() > 0, "No block members"); // Get the right symbol // // This is especially important for e.g. // // for (char *s = 0; char *t = 0;) {} // // The declaration for 's' will be handled in visit(SimpleDeclarationAST *ast), // so handle declaration for 't' here. Scope::iterator it = block->lastMember() - 1; Symbol *symbol = *it; if (symbol && symbol->asScope()) { // True if there is a "{ ... }" following. --it; symbol = *it; } // Specify activation range TokenRange range(condition->firstToken(), declarator->equal_token - 1); checkAndRewrite(declarator, symbol, range); }