diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index 1e8752ba..afd6fb44 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -14,6 +14,14 @@ Storage::~Storage() { } +void Storage::onTypedefParsed( + const ParseLocation& location, const std::string& fullName, const std::string& underlyingFullName, + AccessType access +) +{ + log("typedef", fullName + " -> " + underlyingFullName, location); +} + void Storage::onClassParsed(const ParseLocation& location, const std::string& fullName, AccessType access) { log("class", fullName, location); diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index 61560fc3..26d41f94 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -14,6 +14,10 @@ public: Storage(); virtual ~Storage(); + virtual void onTypedefParsed( + const ParseLocation& location, const std::string& fullName, const std::string& underlyingFullName, + AccessType access + ); virtual void onClassParsed(const ParseLocation& location, const std::string& fullName, AccessType access); virtual void onStructParsed(const ParseLocation& location, const std::string& fullName, AccessType access); diff --git a/src/lib/data/parser/Parser.h b/src/lib/data/parser/Parser.h index 8f0ab342..afa2b969 100644 --- a/src/lib/data/parser/Parser.h +++ b/src/lib/data/parser/Parser.h @@ -7,6 +7,8 @@ #include "data/parser/ParserClient.h" +class TextAccess; + class Parser { public: @@ -14,6 +16,7 @@ public: virtual ~Parser(); virtual void parseFiles(const std::vector& filePaths) = 0; + virtual void parseFile(std::shared_ptr textAccess) = 0; protected: std::shared_ptr m_client; diff --git a/src/lib/data/parser/ParserClient.h b/src/lib/data/parser/ParserClient.h index 7f11217e..e522a601 100644 --- a/src/lib/data/parser/ParserClient.h +++ b/src/lib/data/parser/ParserClient.h @@ -26,6 +26,10 @@ public: ParserClient(); virtual ~ParserClient(); + virtual void onTypedefParsed( + const ParseLocation& location, const std::string& fullName, const std::string& underlyingFullName, + AccessType access + ) = 0; virtual void onClassParsed(const ParseLocation& location, const std::string& fullName, AccessType access) = 0; virtual void onStructParsed(const ParseLocation& location, const std::string& fullName, AccessType access) = 0; diff --git a/src/lib/data/parser/cxx/ASTVisitor.cpp b/src/lib/data/parser/cxx/ASTVisitor.cpp index b5922e21..2f15c302 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.cpp +++ b/src/lib/data/parser/cxx/ASTVisitor.cpp @@ -13,6 +13,23 @@ ASTVisitor::~ASTVisitor() { } +bool ASTVisitor::VisitTypedefDecl(const clang::TypedefDecl* declaration) +{ + const clang::SourceLocation& location = declaration->getLocStart(); + + if (isValidLocation(location)) + { + m_client->onTypedefParsed( + getParseLocation(location), + declaration->getQualifiedNameAsString(), + declaration->getUnderlyingType().getAsString(), + convertAccessType(declaration->getAccess()) + ); + } + + return true; +} + bool ASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* declaration) { const clang::SourceLocation& location = declaration->getLocStart(); diff --git a/src/lib/data/parser/cxx/ASTVisitor.h b/src/lib/data/parser/cxx/ASTVisitor.h index 74f7c590..df234148 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.h +++ b/src/lib/data/parser/cxx/ASTVisitor.h @@ -22,6 +22,7 @@ public: // return false; // } + virtual bool VisitTypedefDecl(const clang::TypedefDecl* declaration); // typedefs virtual bool VisitCXXRecordDecl(clang::CXXRecordDecl* declaration); // classes and structs virtual bool VisitVarDecl(clang::VarDecl* declaration); // global variables and static fields virtual bool VisitFieldDecl(clang::FieldDecl* declaration); // fields diff --git a/src/lib/data/parser/cxx/CxxParser.cpp b/src/lib/data/parser/cxx/CxxParser.cpp index 289a3d71..b0800c9b 100644 --- a/src/lib/data/parser/cxx/CxxParser.cpp +++ b/src/lib/data/parser/cxx/CxxParser.cpp @@ -2,6 +2,7 @@ #include "data/parser/cxx/ASTActionFactory.h" #include "utility/logging/logging.h" +#include "utility/text/TextAccess.h" CxxParser::CxxParser(std::shared_ptr client) : Parser(client) @@ -35,3 +36,9 @@ void CxxParser::parseFiles(const std::vector& filePaths) tool.run(&actionFactory); } + +void CxxParser::parseFile(std::shared_ptr textAccess) +{ + ASTActionFactory actionFactory(m_client); + clang::tooling::runToolOnCode(actionFactory.create(), textAccess->getText()); +} diff --git a/src/lib/data/parser/cxx/CxxParser.h b/src/lib/data/parser/cxx/CxxParser.h index 7dd8e7c5..d785ddb1 100644 --- a/src/lib/data/parser/cxx/CxxParser.h +++ b/src/lib/data/parser/cxx/CxxParser.h @@ -10,6 +10,7 @@ public: ~CxxParser(); virtual void parseFiles(const std::vector& filePaths); + virtual void parseFile(std::shared_ptr textAccess); }; #endif // CXX_PARSER_H diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index 19ca4c84..2e299b87 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -4,6 +4,7 @@ #include "data/parser/ParseLocation.h" #include "data/parser/ParserClient.h" #include "data/parser/ParseVariable.h" +#include "utility/text/TextAccess.h" class CxxParserTestSuite: public CxxTest::TestSuite { @@ -127,10 +128,63 @@ public: TS_ASSERT_EQUALS(client->enumFields[1], "X::E::Q"); } + void test_cxx_parser_finds_typedef_in_global_namespace() + { + std::shared_ptr client = std::make_shared(); + CxxParser parser(client); + std::string text = "typedef unsigned int uint;\n"; + + parser.parseFile(TextAccess::createFromString(text)); + + TS_ASSERT_EQUALS(client->typedefs.size(), 1); + TS_ASSERT_EQUALS(client->typedefs[0], "unsigned int -> uint"); + } + + void test_cxx_parser_finds_typedef_in_named_namespace() + { + std::shared_ptr client = std::make_shared(); + CxxParser parser(client); + std::string text = + "namespace test\n" + "{\n" + " typedef unsigned int uint;\n" + "}\n"; + + parser.parseFile(TextAccess::createFromString(text)); + + TS_ASSERT_EQUALS(client->typedefs.size(), 1); + TS_ASSERT_EQUALS(client->typedefs[0], "unsigned int -> test::uint"); + } + + void test_cxx_parser_finds_typedef_that_uses_type_defined_in_named_namespace() + { + std::shared_ptr client = std::make_shared(); + CxxParser parser(client); + std::string text = + "namespace test\n" + "{\n" + " struct TestStruct{};\n" + "}\n" + "typedef test::TestStruct globalTestStruct;\n"; + + parser.parseFile(TextAccess::createFromString(text)); + + TS_ASSERT_EQUALS(client->typedefs.size(), 1); + TS_ASSERT_EQUALS(client->typedefs[0], "test::TestStruct -> globalTestStruct"); + } + private: class TestParserClient: public ParserClient { public: + virtual void onTypedefParsed( + const ParseLocation& location, const std::string& fullName, const std::string& underlyingFullName, + AccessType access + ) + { + typedefs.push_back(addAccessPrefix(underlyingFullName + " -> " + fullName, access)); + } + virtual void onClassParsed(const ParseLocation& location, const std::string& fullName, AccessType access) { classes.push_back(addAccessPrefix(fullName, access)); @@ -186,6 +240,7 @@ private: enumFields.push_back(fullName); } + std::vector typedefs; std::vector classes; std::vector enums; std::vector enumFields;