QString AbstractEditorSupport::functionAt(const CppModelManagerInterface *modelManager, const QString &fileName, int line, int column) { const CPlusPlus::Snapshot snapshot = modelManager->snapshot(); const CPlusPlus::Document::Ptr document = snapshot.document(fileName); if (!document) return QString(); if (const CPlusPlus::Symbol *symbol = document->lastVisibleSymbolAt(line, column)) if (const CPlusPlus::Scope *scope = symbol->enclosingScope()) if (const CPlusPlus::Scope *functionScope = scope->enclosingFunction()) if (const CPlusPlus::Symbol *function = functionScope) { const CPlusPlus::Overview o; QString rc = o.prettyName(function->name()); // Prepend namespace "Foo::Foo::foo()" up to empty root namespace for (const CPlusPlus::Symbol *owner = function->enclosingNamespace(); owner; owner = owner->enclosingNamespace()) { const QString name = o.prettyName(owner->name()); if (name.isEmpty()) { break; } else { rc.prepend(QLatin1String("::")); rc.prepend(name); } } return rc; } return QString(); }
// Inline helper with integer error return codes. static inline int getUninitializedVariablesI(const CPlusPlus::Snapshot &snapshot, const QString &functionName, const QString &file, int line, QStringList *uninitializedVariables) { uninitializedVariables->clear(); // Find document if (snapshot.isEmpty() || functionName.isEmpty() || file.isEmpty() || line < 1) return 1; const CPlusPlus::Snapshot::const_iterator docIt = snapshot.find(file); if (docIt == snapshot.end()) return 2; const CPlusPlus::Document::Ptr doc = docIt.value(); // Look at symbol at line and find its function. Either it is the // function itself or some expression/variable. const CPlusPlus::Symbol *symbolAtLine = doc->lastVisibleSymbolAt(line, 0); if (!symbolAtLine) return 4; // First figure out the function to do a safety name check // and the innermost scope at cursor position const CPlusPlus::Function *function = 0; const CPlusPlus::Scope *innerMostScope = 0; if (symbolAtLine->isFunction()) { function = symbolAtLine->asFunction(); if (function->memberCount() == 1) // Skip over function block if (CPlusPlus::Block *block = function->memberAt(0)->asBlock()) innerMostScope = block; } else { if (const CPlusPlus::Scope *functionScope = symbolAtLine->enclosingFunction()) { function = functionScope->asFunction(); innerMostScope = symbolAtLine->isBlock() ? symbolAtLine->asBlock() : symbolAtLine->enclosingBlock(); } } if (!function || !innerMostScope) return 7; // Compare function names with a bit off fuzz, // skipping modules from a CDB symbol "lib!foo" or namespaces // that the code model does not show at this point CPlusPlus::Overview overview; const QString name = overview.prettyName(function->name()); if (!functionName.endsWith(name)) return 11; if (functionName.size() > name.size()) { const char previousChar = functionName.at(functionName.size() - name.size() - 1).toLatin1(); if (previousChar != ':' && previousChar != '!' ) return 11; } // Starting from the innermost block scope, collect declarations. SeenHash seenHash; blockRecursion(overview, innerMostScope, line, uninitializedVariables, &seenHash); return 0; }
static void blockRecursion(const CPlusPlus::Overview &overview, const CPlusPlus::Scope *scope, unsigned line, QStringList *uninitializedVariables, SeenHash *seenHash, int level = 0) { // Go backwards in case someone has identical variables in the same scope. // Fixme: loop variables or similar are currently seen in the outer scope for (int s = scope->memberCount() - 1; s >= 0; --s){ const CPlusPlus::Symbol *symbol = scope->memberAt(s); if (symbol->isDeclaration()) { // Find out about shadowed symbols by bookkeeping // the already seen occurrences in a hash. const QString name = overview.prettyName(symbol->name()); SeenHash::iterator it = seenHash->find(name); if (it == seenHash->end()) it = seenHash->insert(name, 0); else ++(it.value()); // Is the declaration on or past the current line, that is, // the variable not initialized. if (symbol->line() >= line) uninitializedVariables->push_back(WatchData::shadowedName(name, it.value())); } } // Next block scope. if (const CPlusPlus::Scope *enclosingScope = scope->enclosingBlock()) blockRecursion(overview, enclosingScope, line, uninitializedVariables, seenHash, level + 1); }