From 78704b64079ad0b3f78693506fe2a8eceba40dc5 Mon Sep 17 00:00:00 2001 From: malte_langkabel Date: Wed, 9 Jul 2014 11:00:35 +0200 Subject: [PATCH] data: complex typename parsing Added DataType class that can be constructed with a clang::qualType. DataType keeps an internal QualifierList and ModifierStack. --- bin/app/data/src/header.h | 21 +++++++ bin/test/data/log/test_log.txt | 8 --- src/lib/CMakeLists.txt | 13 +++++ src/lib/data/parser/cxx/ASTVisitor.cpp | 22 ++------ src/lib/data/parser/cxx/ASTVisitor.h | 2 +- src/lib/data/type/DataType.cpp | 56 +++++++++++++++++++ src/lib/data/type/DataType.h | 27 +++++++++ src/lib/data/type/DataTypeModifierStack.cpp | 35 ++++++++++++ src/lib/data/type/DataTypeModifierStack.h | 25 +++++++++ src/lib/data/type/DataTypeQualifierList.cpp | 35 ++++++++++++ src/lib/data/type/DataTypeQualifierList.h | 31 ++++++++++ .../data/type/modifier/DataTypeModifier.cpp | 24 ++++++++ src/lib/data/type/modifier/DataTypeModifier.h | 24 ++++++++ .../type/modifier/DataTypeModifierPointer.cpp | 14 +++++ .../type/modifier/DataTypeModifierPointer.h | 17 ++++++ .../modifier/DataTypeModifierQualifier.cpp | 33 +++++++++++ .../type/modifier/DataTypeModifierQualifier.h | 28 ++++++++++ src/lib/utility/utilityClang.cpp | 5 ++ src/lib/utility/utilityClang.h | 14 +++++ src/test/CxxParserTestSuite.h | 4 +- 20 files changed, 410 insertions(+), 28 deletions(-) create mode 100644 src/lib/data/type/DataType.cpp create mode 100644 src/lib/data/type/DataType.h create mode 100644 src/lib/data/type/DataTypeModifierStack.cpp create mode 100644 src/lib/data/type/DataTypeModifierStack.h create mode 100644 src/lib/data/type/DataTypeQualifierList.cpp create mode 100644 src/lib/data/type/DataTypeQualifierList.h create mode 100644 src/lib/data/type/modifier/DataTypeModifier.cpp create mode 100644 src/lib/data/type/modifier/DataTypeModifier.h create mode 100644 src/lib/data/type/modifier/DataTypeModifierPointer.cpp create mode 100644 src/lib/data/type/modifier/DataTypeModifierPointer.h create mode 100644 src/lib/data/type/modifier/DataTypeModifierQualifier.cpp create mode 100644 src/lib/data/type/modifier/DataTypeModifierQualifier.h create mode 100644 src/lib/utility/utilityClang.cpp create mode 100644 src/lib/utility/utilityClang.h diff --git a/bin/app/data/src/header.h b/bin/app/data/src/header.h index 40d3d197..82233148 100644 --- a/bin/app/data/src/header.h +++ b/bin/app/data/src/header.h @@ -1,3 +1,24 @@ +/* +class e +{ +}; +class x: public e +{ +}; +struct y; +enum z; + +x foox(); +y fooy(); +z fooz(); +*/ + +const bool *ab(int a, int b); + +bool const *abc(int a, int b); + +bool *const abcd(int a, int b); + int main(); void foo(); int sum(int a, int b); diff --git a/bin/test/data/log/test_log.txt b/bin/test/data/log/test_log.txt index 6d3c3676..e69de29b 100644 --- a/bin/test/data/log/test_log.txt +++ b/bin/test/data/log/test_log.txt @@ -1,8 +0,0 @@ -Graph.cpp ERROR: Can't remove member edge, without removing the child node. -TextAccess.cpp WARNING: Index 'firstLine' has to be lower or equal index 'lastLine', is 2 > 1 -TextAccess.cpp WARNING: Tried to access index 9. Maximum index is 7 -TextAccess.cpp WARNING: Tried to access index 9. Maximum index is 7 -TextAccess.cpp WARNING: Line numbers start with one, is 0 -TextAccess.cpp WARNING: Line numbers start with one, is 0 -TokenLocationCollection.cpp ERROR: Can't create TokenLocation with wrong boundaries. -TokenLocationCollection.cpp ERROR: Can't create TokenLocation with wrong boundaries. diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index f9ed0555..9035567f 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -86,6 +86,17 @@ add_files( data/parser/ParseVariable.cpp data/parser/ParseVariable.h + data/type/modifier/DataTypeModifier.cpp + data/type/modifier/DataTypeModifier.h + data/type/modifier/DataTypeModifierPointer.cpp + data/type/modifier/DataTypeModifierPointer.h + data/type/DataType.cpp + data/type/DataType.h + data/type/DataTypeModifierStack.cpp + data/type/DataTypeModifierStack.h + data/type/DataTypeQualifierList.cpp + data/type/DataTypeQualifierList.h + data/ElementIndex.cpp data/ElementIndex.h data/SearchIndex.cpp @@ -136,6 +147,8 @@ add_files( utility/FileSystem.h utility/Property.h utility/types.h + utility/utilityClang.cpp + utility/utilityClang.h utility/utilityString.cpp utility/utilityString.h utility/Vector.h diff --git a/src/lib/data/parser/cxx/ASTVisitor.cpp b/src/lib/data/parser/cxx/ASTVisitor.cpp index 8992adc4..2182a290 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.cpp +++ b/src/lib/data/parser/cxx/ASTVisitor.cpp @@ -3,6 +3,8 @@ #include "data/parser/cxx/ASTBodyVisitor.h" #include "data/parser/ParseLocation.h" #include "data/parser/ParseVariable.h" +#include "utility/utilityClang.h" +#include "data/type/DataType.h" ASTVisitor::ASTVisitor(clang::ASTContext* context, std::shared_ptr client) : m_context(context) @@ -327,24 +329,10 @@ std::vector ASTVisitor::getParameters(clang::FunctionDecl* declar return parameters; } -std::string ASTVisitor::getTypeName(const clang::QualType& type) const +std::string ASTVisitor::getTypeName(const clang::QualType& qualType) const { - std::string typeName = type.getUnqualifiedType().getAsString(); - - // Remove keywords from type. - std::string keyword; - size_t pos = typeName.find_first_of(' '); - if (pos != std::string::npos) - { - keyword = typeName.substr(0, pos); - } - - if (keyword == "class" || keyword == "struct" || keyword == "enum") - { - typeName = typeName.substr(pos + 1); - } - - return typeName; + DataType dataType(qualType); + return dataType.getRawTypeName(); } ParserClient::AccessType ASTVisitor::convertAccessType(clang::AccessSpecifier access) const diff --git a/src/lib/data/parser/cxx/ASTVisitor.h b/src/lib/data/parser/cxx/ASTVisitor.h index 8414b0af..1d01be07 100644 --- a/src/lib/data/parser/cxx/ASTVisitor.h +++ b/src/lib/data/parser/cxx/ASTVisitor.h @@ -47,7 +47,7 @@ private: ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const; ParseVariable getParseVariable(clang::ValueDecl* declaration) const; std::vector getParameters(clang::FunctionDecl* declaration) const; - std::string getTypeName(const clang::QualType& type) const; + std::string getTypeName(const clang::QualType& qualType) const; ParserClient::AccessType convertAccessType(clang::AccessSpecifier) const; clang::ASTContext* m_context; diff --git a/src/lib/data/type/DataType.cpp b/src/lib/data/type/DataType.cpp new file mode 100644 index 00000000..f7ef8936 --- /dev/null +++ b/src/lib/data/type/DataType.cpp @@ -0,0 +1,56 @@ +#include "data/type/DataType.h" +#include "data/type/modifier/DataTypeModifierPointer.h" + +DataType::DataType(const std::string& typeName) + : m_typeName(typeName) +{ +} + +DataType::DataType(clang::QualType qualType) +{ + while (true) + { + const clang::Type* type = qualType.getTypePtr(); + if (type->isPointerType()) + { + std::shared_ptr modifier = std::make_shared(); + if (qualType.isConstQualified()) + modifier->addQualifier(DataTypeQualifierList::QUALIFIER_CONST); + m_modifierStack.push(modifier); + + qualType = type->getPointeeType(); + } + else if (type->isStructureOrClassType() || type->isEnumeralType()) + { + m_typeName = qualType.getAsString(); + + // we are working on the string here to not lose the namespace information stored in the name. + m_typeName = m_typeName.substr(m_typeName.find(' ') + 1, m_typeName.size() - 1); + + //m_typeName = qualType.getBaseTypeIdentifier()->getName(); // this one does not keep namespace information. + break; + } + else + { + m_typeName = qualType.getUnqualifiedType().getAsString(); + break; + } + } + + if (qualType.isConstQualified()) + m_qualifierList.addQualifier(DataTypeQualifierList::QUALIFIER_CONST); +} + +DataType::~DataType() +{ +} + +std::string DataType::getFullTypeName() const +{ + return m_modifierStack.applyTo(m_qualifierList.applyTo(m_typeName)); +} + +std::string DataType::getRawTypeName() const +{ + return m_typeName; +} diff --git a/src/lib/data/type/DataType.h b/src/lib/data/type/DataType.h new file mode 100644 index 00000000..bd045876 --- /dev/null +++ b/src/lib/data/type/DataType.h @@ -0,0 +1,27 @@ +#ifndef DATA_TYPE_H +#define DATA_TYPE_H + +#include +#include + +#include "clang/AST/Type.h" + +#include "data/type/DataTypeModifierStack.h" + +class DataType +{ +public: + DataType(clang::QualType qualType); + DataType(const std::string& typeName); + ~DataType(); + + std::string getFullTypeName() const; + std::string getRawTypeName() const; + +private: + std::string m_typeName; + DataTypeQualifierList m_qualifierList; + DataTypeModifierStack m_modifierStack; +}; + +#endif // DATA_TYPE_H diff --git a/src/lib/data/type/DataTypeModifierStack.cpp b/src/lib/data/type/DataTypeModifierStack.cpp new file mode 100644 index 00000000..5d2d78aa --- /dev/null +++ b/src/lib/data/type/DataTypeModifierStack.cpp @@ -0,0 +1,35 @@ +#include "data/type/DataTypeModifierStack.h" + +DataTypeModifierStack::DataTypeModifierStack() +{ +} + +//DataTypeModifierStack::DataTypeModifierStack(const DataTypeModifierStack& o) +//{ +// for (std::shared_ptr modifier: o.m_modifiers) +// { +// m_modifiers.push_back(modifier.); +// } +//} + + +DataTypeModifierStack::~DataTypeModifierStack() +{ +} + + +void DataTypeModifierStack::push(std::shared_ptr modifier) +{ + m_modifiers.push_back(modifier); +} + + +std::string DataTypeModifierStack::applyTo(const std::string& typeName) const +{ + std::string modifiedTypeName = typeName; + for (std::shared_ptr modifier: m_modifiers) + { + modifier->applyTo(modifiedTypeName); + } + return modifiedTypeName; +} diff --git a/src/lib/data/type/DataTypeModifierStack.h b/src/lib/data/type/DataTypeModifierStack.h new file mode 100644 index 00000000..d3939065 --- /dev/null +++ b/src/lib/data/type/DataTypeModifierStack.h @@ -0,0 +1,25 @@ +#ifndef DATA_TYPE_MODIFIER_STACK_H +#define DATA_TYPE_MODIFIER_STACK_H + +#include +#include +#include + +#include "data/type/modifier/DataTypeModifier.h" + +class DataTypeModifierStack +{ +public: + DataTypeModifierStack(); + //DataTypeModifierStack(const DataTypeModifierStack& o); + ~DataTypeModifierStack(); + + void push(std::shared_ptr modifier); + + std::string applyTo(const std::string& typeName) const; + +private: + std::vector> m_modifiers; +}; + +#endif // DATA_TYPE_MODIFIER_STACK_H diff --git a/src/lib/data/type/DataTypeQualifierList.cpp b/src/lib/data/type/DataTypeQualifierList.cpp new file mode 100644 index 00000000..e7fe6661 --- /dev/null +++ b/src/lib/data/type/DataTypeQualifierList.cpp @@ -0,0 +1,35 @@ +#include "data/type/DataTypeQualifierList.h" + +DataTypeQualifierList::DataTypeQualifierList() + : m_qualifiers(QUALIFIER_NONE) +{ +} + +DataTypeQualifierList::~DataTypeQualifierList() +{ +} + +void DataTypeQualifierList::addQualifier(QualifierType qualifier) +{ + m_qualifiers = m_qualifiers | qualifier; +} + +void DataTypeQualifierList::removeQualifier(QualifierType qualifier) +{ + m_qualifiers = m_qualifiers & ~qualifier; +} + +bool DataTypeQualifierList::hasQualifier(QualifierType qualifier) const +{ + return (m_qualifiers & qualifier) > 0; +} + +std::string DataTypeQualifierList::applyTo(const std::string& typeName) const +{ + std::string qualifiedTypeName = typeName; + if (hasQualifier(QUALIFIER_CONST)) + { + qualifiedTypeName += " const"; + } + return qualifiedTypeName; +} \ No newline at end of file diff --git a/src/lib/data/type/DataTypeQualifierList.h b/src/lib/data/type/DataTypeQualifierList.h new file mode 100644 index 00000000..dd28afe1 --- /dev/null +++ b/src/lib/data/type/DataTypeQualifierList.h @@ -0,0 +1,31 @@ +#ifndef DATA_TYPE_QUALIFIER_H +#define DATA_TYPE_QUALIFIER_H + +#include +#include + +#include "clang/AST/Type.h" + +class DataTypeQualifierList +{ +public: + enum QualifierType + { + QUALIFIER_NONE = 0, + QUALIFIER_CONST = 1 + }; + + DataTypeQualifierList(); + ~DataTypeQualifierList(); + + void addQualifier(QualifierType qualifier); + void removeQualifier(QualifierType qualifier); + bool hasQualifier(QualifierType qualifier) const; + + std::string applyTo(const std::string& typeName) const; + +private: + char m_qualifiers; +}; + +#endif // DATA_TYPE_H diff --git a/src/lib/data/type/modifier/DataTypeModifier.cpp b/src/lib/data/type/modifier/DataTypeModifier.cpp new file mode 100644 index 00000000..80d44adc --- /dev/null +++ b/src/lib/data/type/modifier/DataTypeModifier.cpp @@ -0,0 +1,24 @@ +#include "data/type/modifier/DataTypeModifier.h" + +DataTypeModifier::DataTypeModifier() +{ +} + +DataTypeModifier::~DataTypeModifier() +{ +} + +void DataTypeModifier::addQualifier(DataTypeQualifierList::QualifierType qualifier) +{ + m_qualifierList.addQualifier(qualifier); +} + +void DataTypeModifier::removeQualifier(DataTypeQualifierList::QualifierType qualifier) +{ + m_qualifierList.removeQualifier(qualifier); +} + +bool DataTypeModifier::hasQualifier(DataTypeQualifierList::QualifierType qualifier) const +{ + return m_qualifierList.hasQualifier(qualifier); +} \ No newline at end of file diff --git a/src/lib/data/type/modifier/DataTypeModifier.h b/src/lib/data/type/modifier/DataTypeModifier.h new file mode 100644 index 00000000..d9c1bf81 --- /dev/null +++ b/src/lib/data/type/modifier/DataTypeModifier.h @@ -0,0 +1,24 @@ +#ifndef DATA_TYPE_MODIFIER_H +#define DATA_TYPE_MODIFIER_H + +#include + +#include "data/type/DataTypeQualifierList.h" + +class DataTypeModifier +{ +public: + DataTypeModifier(); + virtual ~DataTypeModifier(); + + virtual void applyTo(std::string& typeName) const = 0; + + void addQualifier(DataTypeQualifierList::QualifierType qualifier); + void removeQualifier(DataTypeQualifierList::QualifierType qualifier); + bool hasQualifier(DataTypeQualifierList::QualifierType qualifier) const; + +private: + DataTypeQualifierList m_qualifierList; +}; + +#endif // DATA_TYPE_MODIFIER_H diff --git a/src/lib/data/type/modifier/DataTypeModifierPointer.cpp b/src/lib/data/type/modifier/DataTypeModifierPointer.cpp new file mode 100644 index 00000000..d80f798b --- /dev/null +++ b/src/lib/data/type/modifier/DataTypeModifierPointer.cpp @@ -0,0 +1,14 @@ +#include "data/type/modifier/DataTypeModifierPointer.h" + +DataTypeModifierPointer::DataTypeModifierPointer() +{ +} + +DataTypeModifierPointer::~DataTypeModifierPointer() +{ +} + +void DataTypeModifierPointer::applyTo(std::string& typeName) const +{ + typeName.append(" *"); +} diff --git a/src/lib/data/type/modifier/DataTypeModifierPointer.h b/src/lib/data/type/modifier/DataTypeModifierPointer.h new file mode 100644 index 00000000..a0168e3a --- /dev/null +++ b/src/lib/data/type/modifier/DataTypeModifierPointer.h @@ -0,0 +1,17 @@ +#ifndef DATA_TYPE_MODIFIER_POINTER_H +#define DATA_TYPE_MODIFIER_POINTER_H + +#include "data/type/modifier/DataTypeModifier.h" + +class DataTypeModifierPointer: public DataTypeModifier +{ +public: + DataTypeModifierPointer(); + virtual ~DataTypeModifierPointer(); + + virtual void applyTo(std::string& typeName) const; + + +}; + +#endif // DATA_TYPE_MODIFIER_POINTER_H diff --git a/src/lib/data/type/modifier/DataTypeModifierQualifier.cpp b/src/lib/data/type/modifier/DataTypeModifierQualifier.cpp new file mode 100644 index 00000000..a9112d6c --- /dev/null +++ b/src/lib/data/type/modifier/DataTypeModifierQualifier.cpp @@ -0,0 +1,33 @@ +#include "data/type/modifier/DataTypeModifierQualifier.h" + +DataTypeModifierQualifier::DataTypeModifierQualifier() + : m_qualifiers(QUALIFIER_NONE) +{ +} + +DataTypeModifierQualifier::~DataTypeModifierQualifier() +{ +} + +void DataTypeModifierQualifier::addQualifier(QualifierType qualifier) +{ + m_qualifiers = m_qualifiers | qualifier; +} + +void DataTypeModifierQualifier::removeQualifier(QualifierType qualifier) +{ + m_qualifiers = m_qualifiers & ~qualifier; +} + +bool DataTypeModifierQualifier::hasQualifier(QualifierType qualifier) const +{ + return (m_qualifiers & qualifier) > 0; +} + +void DataTypeModifierQualifier::applyTo(std::string& typeName) const +{ + if (hasQualifier) + { + typeName.append(" const"); + } +} diff --git a/src/lib/data/type/modifier/DataTypeModifierQualifier.h b/src/lib/data/type/modifier/DataTypeModifierQualifier.h new file mode 100644 index 00000000..e166a0ef --- /dev/null +++ b/src/lib/data/type/modifier/DataTypeModifierQualifier.h @@ -0,0 +1,28 @@ +#ifndef DATA_TYPE_MODIFIER_QUALIFIER_H +#define DATA_TYPE_MODIFIER_QUALIFIER_H + +#include "data/type/modifier/DataTypeModifier.h" + +class DataTypeModifierQualifier: public DataTypeModifier +{ +public: + enum QualifierType + { + QUALIFIER_NONE = 0, + QUALIFIER_CONST = 1 + }; + + DataTypeModifierQualifier(); + virtual ~DataTypeModifierQualifier(); + + void addQualifier(QualifierType qualifier); + void removeQualifier(QualifierType qualifier); + bool hasQualifier(QualifierType qualifier) const; + + virtual void applyTo(std::string& typeName) const; + +private: + char m_qualifiers; +}; + +#endif // DATA_TYPE_MODIFIER_QUALIFIER_H diff --git a/src/lib/utility/utilityClang.cpp b/src/lib/utility/utilityClang.cpp new file mode 100644 index 00000000..a2f2e828 --- /dev/null +++ b/src/lib/utility/utilityClang.cpp @@ -0,0 +1,5 @@ +#include "utility/utilityClang.h" + +namespace utility +{ +} diff --git a/src/lib/utility/utilityClang.h b/src/lib/utility/utilityClang.h new file mode 100644 index 00000000..deb079e6 --- /dev/null +++ b/src/lib/utility/utilityClang.h @@ -0,0 +1,14 @@ +#ifndef UTILITY_CLANG_H +#define UTILITY_CLANG_H + +#include + +#include "clang/AST/Type.h" + +class DataType; + +namespace utility +{ +} + +#endif // UTILITY_CLANG_H diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index 864ec89c..373932f4 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -123,7 +123,7 @@ public: TS_ASSERT_EQUALS(client->globalVariables.size(), 2); TS_ASSERT_EQUALS(client->globalVariables[0], "int x <1:1 1:5>"); - TS_ASSERT_EQUALS(client->globalVariables[1], "A * b <3:1 3:4>"); + TS_ASSERT_EQUALS(client->globalVariables[1], "A b <3:1 3:4>"); // Todo: what about the pointer? } void test_cxx_parser_finds_variable_definitions_in_namespace_scope() @@ -139,7 +139,7 @@ public: TS_ASSERT_EQUALS(client->globalVariables.size(), 2); TS_ASSERT_EQUALS(client->globalVariables[0], "int n::x <2:2 2:6>"); - TS_ASSERT_EQUALS(client->globalVariables[1], "n::A * n::b <4:2 4:5>"); + TS_ASSERT_EQUALS(client->globalVariables[1], "n::A n::b <4:2 4:5>"); // Todo: what about the pointer? } void test_cxx_parser_finds_field_in_nested_class()