From f3c8500fa9c7422ffd693c02a2bb7c9fb01b3bc5 Mon Sep 17 00:00:00 2001 From: Jacob Dufault Date: Fri, 10 Mar 2017 18:24:51 -0800 Subject: [PATCH] fixes, print diagnostics --- clang_args | 2 + indexer.cpp | 154 ++++++++++++++++++++++++++++++++++++---------------- indexer.h | 4 ++ test.cc | 6 +- utils.cc | 16 +++--- utils.h | 2 +- 6 files changed, 125 insertions(+), 59 deletions(-) create mode 100644 clang_args diff --git a/clang_args b/clang_args new file mode 100644 index 00000000..1f034de8 --- /dev/null +++ b/clang_args @@ -0,0 +1,2 @@ +-std=c++11 +-Ithird_party/rapidjson/include \ No newline at end of file diff --git a/indexer.cpp b/indexer.cpp index 9e540466..128afb09 100644 --- a/indexer.cpp +++ b/indexer.cpp @@ -97,6 +97,28 @@ void IndexedTypeDef::AddUsage(Location loc, bool insert_if_not_present) { uses.push_back(loc); } + +std::string Location::ToPrettyString(IdCache* id_cache) { + // Output looks like this: + // + // *1:2:3 + // + // * => interesting + // 1 => file id + // 2 => line + // 3 => column + + std::string result; + if (interesting) + result += '*'; + result += id_cache->file_id_to_file_path[raw_file_id]; + result += ':'; + result += std::to_string(line); + result += ':'; + result += std::to_string(column); + return result; +} + IdCache::IdCache() { // Reserve id 0 for unfound. file_path_to_file_id[""] = FileId(0); @@ -154,7 +176,53 @@ bool Contains(const std::vector& vec, const T& element) { +struct NamespaceHelper { + std::unordered_map container_usr_to_qualified_name; + void RegisterQualifiedName(std::string usr, const CXIdxContainerInfo* container, std::string qualified_name) { + if (container) { + std::string container_usr = clang::Cursor(container->cursor).get_usr(); + auto it = container_usr_to_qualified_name.find(container_usr); + if (it != container_usr_to_qualified_name.end()) { + container_usr_to_qualified_name[usr] = it->second + qualified_name + "::"; + return; + } + } + + container_usr_to_qualified_name[usr] = qualified_name + "::"; + } + + std::string QualifiedName(const CXIdxContainerInfo* container, std::string unqualified_name) { + if (container) { + std::string container_usr = clang::Cursor(container->cursor).get_usr(); + auto it = container_usr_to_qualified_name.find(container_usr); + if (it != container_usr_to_qualified_name.end()) + return it->second + unqualified_name; + + // Anonymous namespaces are not processed by indexDeclaration. If we + // encounter one insert it into map. + if (container->cursor.kind == CXCursor_Namespace) { + //assert(clang::Cursor(container->cursor).get_spelling() == ""); + container_usr_to_qualified_name[container_usr] = "::"; + return "::" + unqualified_name; + } + } + return unqualified_name; + } +}; + +struct IndexParam { + IndexedFile* db; + NamespaceHelper* ns; + + // Record the last type usage location we recorded. Clang will sometimes + // visit the same expression twice so we wan't to avoid double-reporting + // usage information for those locations. + Location last_type_usage_location; + Location last_func_usage_location; + + IndexParam(IndexedFile* db, NamespaceHelper* ns) : db(db), ns(ns) {} +}; @@ -166,7 +234,38 @@ int abortQuery(CXClientData client_data, void *reserved) { // 0 -> continue return 0; } -void diagnostic(CXClientData client_data, CXDiagnosticSet, void *reserved) {} +void diagnostic(CXClientData client_data, CXDiagnosticSet diagnostics, void *reserved) { + IndexParam* param = static_cast(client_data); + + std::cerr << "!! Got diagnostic" << std::endl; + /** + * \brief Determine the number of diagnostics in a CXDiagnosticSet. + */ + //CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags); + + for (unsigned i = 0; i < clang_getNumDiagnosticsInSet(diagnostics); ++i) { + CXDiagnostic diagnostic = clang_getDiagnosticInSet(diagnostics, i); + + std::string spelling = clang::ToString(clang_getDiagnosticSpelling(diagnostic)); + Location location = param->db->id_cache.Resolve(clang_getDiagnosticLocation(diagnostic), false /*interesting*/); + + std::cerr << location.ToPrettyString(¶m->db->id_cache) << ": " << spelling << std::endl; + + clang_disposeDiagnostic(diagnostic); + } + /** + * \brief Retrieve a diagnostic associated with the given CXDiagnosticSet. + * + * \param Diags the CXDiagnosticSet to query. + * \param Index the zero-based diagnostic number to retrieve. + * + * \returns the requested diagnostic. This diagnostic must be freed + * via a call to \c clang_disposeDiagnostic(). + */ + // CINDEX_LINKAGE CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags, + // unsigned Index); + +} CXIdxClientFile enteredMainFile(CXClientData client_data, CXFile mainFile, void *reserved) { return nullptr; @@ -258,53 +357,6 @@ optional FindType(clang::Cursor cursor) { -struct NamespaceHelper { - std::unordered_map container_usr_to_qualified_name; - - void RegisterQualifiedName(std::string usr, const CXIdxContainerInfo* container, std::string qualified_name) { - if (container) { - std::string container_usr = clang::Cursor(container->cursor).get_usr(); - auto it = container_usr_to_qualified_name.find(container_usr); - if (it != container_usr_to_qualified_name.end()) { - container_usr_to_qualified_name[usr] = it->second + qualified_name + "::"; - return; - } - } - - container_usr_to_qualified_name[usr] = qualified_name + "::"; - } - - std::string QualifiedName(const CXIdxContainerInfo* container, std::string unqualified_name) { - if (container) { - std::string container_usr = clang::Cursor(container->cursor).get_usr(); - auto it = container_usr_to_qualified_name.find(container_usr); - if (it != container_usr_to_qualified_name.end()) - return it->second + unqualified_name; - - // Anonymous namespaces are not processed by indexDeclaration. If we - // encounter one insert it into map. - if (container->cursor.kind == CXCursor_Namespace) { - //assert(clang::Cursor(container->cursor).get_spelling() == ""); - container_usr_to_qualified_name[container_usr] = "::"; - return "::" + unqualified_name; - } - } - return unqualified_name; - } -}; - -struct IndexParam { - IndexedFile* db; - NamespaceHelper* ns; - - // Record the last type usage location we recorded. Clang will sometimes - // visit the same expression twice so we wan't to avoid double-reporting - // usage information for those locations. - Location last_type_usage_location; - Location last_func_usage_location; - - IndexParam(IndexedFile* db, NamespaceHelper* ns) : db(db), ns(ns) {} -}; /* std::string GetNamespacePrefx(const CXIdxDeclInfo* decl) { @@ -1031,6 +1083,12 @@ struct Timer { }; IndexedFile Parse(std::string filename, std::vector args, bool dump_ast) { + args.push_back("-std=c++11"); + args.push_back("-fms-compatibility"); + args.push_back("-fdelayed-template-parsing"); + //args.push_back("-isystem C:\\Users\\jacob\\Desktop\\superindex\\indexer\\libcxx-3.9.1\\include"); + //args.push_back("--sysroot C:\\Users\\jacob\\Desktop\\superindex\\indexer\\libcxx-3.9.1"); + clang::Index index(0 /*excludeDeclarationsFromPCH*/, 0 /*displayDiagnostics*/); clang::TranslationUnit tu(index, filename, args); diff --git a/indexer.h b/indexer.h index ce324453..8d4eb192 100644 --- a/indexer.h +++ b/indexer.h @@ -64,6 +64,8 @@ using TypeId = Id; using FuncId = Id; using VarId = Id; +class IdCache; + struct Location { bool interesting; int raw_file_id; @@ -113,6 +115,8 @@ struct Location { column = atoi(encoded); } + std::string ToPrettyString(IdCache* id_cache); + std::string ToString() { // Output looks like this: // diff --git a/test.cc b/test.cc index 0fcb31c4..355b92ba 100644 --- a/test.cc +++ b/test.cc @@ -95,9 +95,9 @@ void RunTests() { return 0; */ - for (std::string path : GetFilesInFolder("tests", true /*add_folder_to_path*/)) { + for (std::string path : GetFilesInFolder("tests", true /*recursive*/, true /*add_folder_to_path*/)) { //if (path != "tests/templates/specialized_func_definition.cc") continue; - if (path != "tests/outline/outline.cc") continue; + if (path != "tests/outline/outline2.h") continue; //if (path == "tests/inheritance/class_inherit_templated_parent.cc") continue; //if (path != "tests/namespaces/namespace_reference.cc") continue; //if (path != "tests/stl.cc") continue; @@ -113,7 +113,7 @@ void RunTests() { // Run test. std::cout << "[START] " << path << std::endl; - IndexedFile db = Parse(path, {}, true /*dump_ast*/); + IndexedFile db = Parse(path, {}, false /*dump_ast*/); VerifySerializeToFrom(db); std::string actual_output = db.ToString(); diff --git a/utils.cc b/utils.cc index 8029c0e5..08369655 100644 --- a/utils.cc +++ b/utils.cc @@ -6,7 +6,7 @@ #include "tinydir.h" -static std::vector GetFilesInFolderHelper(std::string folder, std::string output_prefix) { +static std::vector GetFilesInFolderHelper(std::string folder, bool recursive, std::string output_prefix) { std::vector result; tinydir_dir dir; @@ -25,10 +25,12 @@ static std::vector GetFilesInFolderHelper(std::string folder, std:: // Skip all dot files. if (file.name[0] != '.') { if (file.is_dir) { - // Note that we must always ignore the '.' and '..' directories, otherwise - // this will loop infinitely. The above check handles that for us. - for (std::string nested_file : GetFilesInFolderHelper(file.path, output_prefix + file.name + "/")) - result.push_back(nested_file); + if (recursive) { + // Note that we must always ignore the '.' and '..' directories, otherwise + // this will loop infinitely. The above check handles that for us. + for (std::string nested_file : GetFilesInFolderHelper(file.path, true /*recursive*/, output_prefix + file.name + "/")) + result.push_back(nested_file); + } } else { result.push_back(output_prefix + file.name); @@ -46,12 +48,12 @@ bail: return result; } -std::vector GetFilesInFolder(std::string folder, bool add_folder_to_path) { +std::vector GetFilesInFolder(std::string folder, bool recursive, bool add_folder_to_path) { assert(folder.size() > 0); if (folder[folder.size() - 1] != '/') folder += '/'; - return GetFilesInFolderHelper(folder, add_folder_to_path ? folder : ""); + return GetFilesInFolderHelper(folder, recursive, add_folder_to_path ? folder : ""); } // http://stackoverflow.com/a/6089413 diff --git a/utils.h b/utils.h index 90a0042b..be1f5979 100644 --- a/utils.h +++ b/utils.h @@ -5,7 +5,7 @@ #include // Finds all files in the given folder. This is recursive. -std::vector GetFilesInFolder(std::string folder, bool add_folder_to_path); +std::vector GetFilesInFolder(std::string folder, bool recursive, bool add_folder_to_path); std::vector ReadLines(std::string filename); void ParseTestExpectation(std::string filename, std::string* expected_output);