FileLocation findDefinitionLocation(const FileLocation& location) { // bail if we aren't initialized if (!s_initialized) return FileLocation(); // get the definition cursor for this file location Cursor cursor = rSourceIndex().referencedCursorForFileLocation(location); if (cursor.isNull()) return FileLocation(); // get the USR for the cursor and search for it std::string USR = cursor.getUSR(); if (!USR.empty()) { // first inspect translation units we have an in-memory index for TranslationUnits units = rSourceIndex().getIndexedTranslationUnits(); BOOST_FOREACH(const TranslationUnits::value_type& unit, units) { // search for the definition CppDefinition def; DefinitionVisitor visitor = boost::bind(findUSR, USR, _1, &def); // visit the cursors libclang::clang().visitChildren( libclang::clang().getTranslationUnitCursor( unit.second.getCXTranslationUnit()), cursorVisitor, (CXClientData)&visitor); // return the definition if we found it if (!def.empty()) return def.location; }
core::Error findReferences(const core::libclang::FileLocation& location, std::string* pSpelling, std::vector<core::libclang::FileRange>* pRefs) { Cursor cursor = rSourceIndex().referencedCursorForFileLocation(location); if (!cursor.isValid() || !cursor.isDeclaration()) return Success(); // get it's USR (bail if it doesn't have one) std::string USR = cursor.getUSR(); if (USR.empty()) return Success(); // determine what translation units to look in -- if this is a package // then we look throughout all the source code in the package. if (rCompilationDatabase().hasTranslationUnit( location.filePath.absolutePath())) { // get all translation units to search std::vector<std::string> files = rCompilationDatabase() .translationUnits(); // get translation units we've already indexed std::map<std::string,TranslationUnit> indexedUnits = rSourceIndex().getIndexedTranslationUnits(); for (const std::string& filename : files) { // first look in already indexed translation units // (this will pickup unsaved files) std::map<std::string,TranslationUnit>::iterator it = indexedUnits.find(filename); if (it != indexedUnits.end()) { findReferences(USR, it->second.getCXTranslationUnit(), pSpelling, pRefs); } else { // get the compilation arguments for this file and use them to // create a temporary translation unit to search std::vector<std::string> compileArgs = rCompilationDatabase().compileArgsForTranslationUnit(filename, true); if (compileArgs.empty()) continue; // create temporary index CXIndex index = libclang::clang().createIndex( 1 /* Exclude PCH */, (rSourceIndex().verbose() > 0) ? 1 : 0); // get args in form clang expects core::system::ProcessArgs argsArray(compileArgs); // parse the translation unit CXTranslationUnit tu = libclang::clang().parseTranslationUnit( index, filename.c_str(), argsArray.args(), gsl::narrow_cast<int>(argsArray.argCount()), nullptr, 0, // no unsaved files CXTranslationUnit_None | CXTranslationUnit_Incomplete); // find references findReferences(USR, tu, pSpelling, pRefs); // dispose translation unit and index libclang::clang().disposeTranslationUnit(tu); libclang::clang().disposeIndex(index); } } } // not a package, just search locally else { TranslationUnit tu = rSourceIndex().getTranslationUnit( location.filePath.absolutePath(), true); if (!tu.empty()) findReferences(USR, tu.getCXTranslationUnit(), pSpelling, pRefs); } return Success(); }