static QString fullyQualifiedName(Symbol *symbol, const Overview *overview) { QStringList nestedNameSpecifier; for (Scope *scope = symbol->scope(); scope && scope->enclosingScope(); scope = scope->enclosingScope()) { Symbol *owner = scope->owner(); if (! owner) { qWarning() << "invalid scope."; // ### better message. continue; } if (! owner->name()) nestedNameSpecifier.prepend(QLatin1String("$anonymous")); else { const QString name = overview->prettyName(owner->name()); nestedNameSpecifier.prepend(name); } } nestedNameSpecifier.append(overview->prettyName(symbol->name())); return nestedNameSpecifier.join(QLatin1String("::")); }
/// Return all typedefs with given name from given scope up to function scope. QList<LookupItem> TypeResolver::typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope) { QList<LookupItem> results; if (!scope) return results; Scope *enclosingBlockScope = 0; for (Block *block = scope->asBlock(); block; block = enclosingBlockScope ? enclosingBlockScope->asBlock() : 0) { const unsigned memberCount = block->memberCount(); for (unsigned i = 0; i < memberCount; ++i) { Symbol *symbol = block->memberAt(i); if (Declaration *declaration = symbol->asDeclaration()) { if (isTypedefWithName(declaration, name)) { LookupItem item; item.setDeclaration(declaration); item.setScope(block); item.setType(declaration->type()); results.append(item); } } } enclosingBlockScope = block->enclosingScope(); if (enclosingBlockScope) { // For lambda, step beyond the function to its enclosing block if (Function *enclosingFunction = enclosingBlockScope->asFunction()) { if (!enclosingFunction->name()) enclosingBlockScope = enclosingBlockScope->enclosingScope(); } } } return results; }
Block *Symbol::enclosingBlock() const { for (Scope *s = _enclosingScope; s; s = s->enclosingScope()) { if (Block *block = s->asBlock()) return block; } return 0; }
Function *Symbol::enclosingFunction() const { for (Scope *s = _enclosingScope; s; s = s->enclosingScope()) { if (Function *fun = s->asFunction()) return fun; } return 0; }
Enum *Symbol::enclosingEnum() const { for (Scope *s = _enclosingScope; s; s = s->enclosingScope()) { if (Enum *e = s->asEnum()) return e; } return 0; }
Class *Symbol::enclosingClass() const { for (Scope *s = _enclosingScope; s; s = s->enclosingScope()) { if (Class *klass = s->asClass()) return klass; } return 0; }
Template *Symbol::enclosingTemplate() const { for (Scope *s = _enclosingScope; s; s = s->enclosingScope()) { if (Template *templ = s->asTemplate()) return templ; } return 0; }
Namespace *Symbol::enclosingNamespace() const { for (Scope *s = _enclosingScope; s; s = s->enclosingScope()) { if (Namespace *ns = s->asNamespace()) return ns; } return 0; }
Scope *Scope::enclosingNamespaceScope() const { Scope *scope = enclosingScope(); for (; scope; scope = scope->enclosingScope()) { if (scope->owner()->isNamespace()) break; } return scope; }
Scope *Scope::enclosingBlockScope() const { Scope *scope = enclosingScope(); for (; scope; scope = scope->enclosingScope()) { if (scope->owner()->isBlock()) break; } return scope; }
Scope *Scope::enclosingFunctionScope() const { Scope *scope = enclosingScope(); for (; scope; scope = scope->enclosingScope()) { if (scope->owner()->isFunction()) break; } return scope; }
Scope *Scope::enclosingClassScope() const { Scope *scope = enclosingScope(); for (; scope; scope = scope->enclosingScope()) { if (scope->owner()->isClass()) break; } return scope; }
// TODO: remove me, this is taken from cppeditor.cpp. Find some common place for this method static Document::Ptr findDefinition(const Function *functionDeclaration, int *line) { CppTools::CppModelManagerInterface *cppModelManager = cppModelManagerInstance(); if (!cppModelManager) return Document::Ptr(); QVector<const Name *> qualifiedName; Scope *scope = functionDeclaration->scope(); for (; scope; scope = scope->enclosingScope()) { if (scope->isClassScope() || scope->isNamespaceScope()) { if (scope->owner() && scope->owner()->name()) { const Name *scopeOwnerName = scope->owner()->name(); if (const QualifiedNameId *q = scopeOwnerName->asQualifiedNameId()) { for (unsigned i = 0; i < q->nameCount(); ++i) { qualifiedName.prepend(q->nameAt(i)); } } else { qualifiedName.prepend(scopeOwnerName); } } } } qualifiedName.append(functionDeclaration->name()); Control control; const QualifiedNameId *q = control.qualifiedNameId(&qualifiedName[0], qualifiedName.size()); LookupContext context(&control); const Snapshot documents = cppModelManager->snapshot(); foreach (Document::Ptr doc, documents) { QList<Scope *> visibleScopes; visibleScopes.append(doc->globalSymbols()); visibleScopes = context.expand(visibleScopes); foreach (Scope *visibleScope, visibleScopes) { Symbol *symbol = 0; if (const NameId *nameId = q->unqualifiedNameId()->asNameId()) symbol = visibleScope->lookat(nameId->identifier()); else if (const DestructorNameId *dtorId = q->unqualifiedNameId()->asDestructorNameId()) symbol = visibleScope->lookat(dtorId->identifier()); else if (const TemplateNameId *templNameId = q->unqualifiedNameId()->asTemplateNameId()) symbol = visibleScope->lookat(templNameId->identifier()); else if (const OperatorNameId *opId = q->unqualifiedNameId()->asOperatorNameId()) symbol = visibleScope->lookat(opId->kind()); // ### cast operators for (; symbol; symbol = symbol->next()) { if (! symbol->isFunction()) continue; else if (! isCompatible(symbol->asFunction(), functionDeclaration, q)) continue; *line = symbol->line(); // TODO: shift the line so that we are inside a function. Maybe just find the nearest '{'? return doc; } }
/*! * 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); }