int test_main(int argc, char * argv[]) { try { // setup log initializeStderrLog("coredev", ::core::system::kLogLevelWarning); // ignore sigpipe Error error = ::core::system::ignoreSignal(::core::system::SigPipe); if (error) LOG_ERROR(error); // write a C++ file std::string cpp = "#include <string>\n" "class X { public:\n" " void test(int y, int x = 10);\n" "}\n" "void X::test(int y, int x) {}\n" "void foobar() {\n" " X x;\n" " x." "}"; std::ofstream ostr("foo.cpp"); ostr << cpp; ostr.close(); // load libclang using namespace libclang; std::string diagnostics; clang().load(EmbeddedLibrary(), LibraryVersion(3,4,0), &diagnostics); if (!clang().isLoaded()) { std::cerr << "Failed to load libclang: " << diagnostics << std::endl; return EXIT_FAILURE; } // create a source index and get a translation unit for it SourceIndex sourceIndex; TranslationUnit tu = sourceIndex.getTranslationUnit("foo.cpp"); if (tu.empty()) { std::cerr << "No translation unit foo.cpp" << std::endl; return EXIT_FAILURE; } // code complete CodeCompleteResults results = tu.codeCompleteAt("foo.cpp", 8, 6); for (unsigned i = 0; i<results.getNumResults(); i++) { std::cout << results.getResult(i).getTypedText() << std::endl; std::cout << " " << results.getResult(i).getText() << std::endl; } return EXIT_SUCCESS; } CATCH_UNEXPECTED_EXCEPTION // if we got this far we had an unexpected exception return EXIT_FAILURE ; }
Error getCppCompletions(const core::json::JsonRpcRequest& request, core::json::JsonRpcResponse* pResponse) { // get params std::string docPath, userText; int line, column; Error error = json::readParams(request.params, &docPath, &line, &column, &userText); if (error) return error; // resolve the docPath if it's aliased FilePath filePath = module_context::resolveAliasedPath(docPath); // get the translation unit and do the code completion std::string filename = filePath.absolutePath(); TranslationUnit tu = rSourceIndex().getTranslationUnit(filename); if (!tu.empty()) { std::string lastTypedText; json::Array completionsJson; boost::shared_ptr<CodeCompleteResults> pResults = tu.codeCompleteAt(filename, line, column); if (!pResults->empty()) { // get results for (unsigned i = 0; i<pResults->getNumResults(); i++) { CodeCompleteResult result = pResults->getResult(i); // filter on user text if we have it if (!userText.empty() && !boost::algorithm::starts_with(result.getTypedText(), userText)) { continue; } // check whether this completion is valid and bail if not if (result.getAvailability() != CXAvailability_Available) { continue; } std::string typedText = result.getTypedText(); // if we have the same typed text then just ammend previous result if ((typedText == lastTypedText) && !completionsJson.empty()) { json::Object& res = completionsJson.back().get_obj(); json::Array& text = res["text"].get_array(); text.push_back(friendlyCompletionText(result)); } else { completionsJson.push_back(toJson(result)); } lastTypedText = typedText; } } json::Object resultJson; resultJson["completions"] = completionsJson; pResponse->setResult(resultJson); } else { // set null result indicating this file doesn't support completions pResponse->setResult(json::Value()); } return Success(); }
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(); }