data: basic template parsing
* Implemented basic parsing and storage of template parameter types, template classes and template functions * Added template specialization edge. * Implemented handling of partial specializations. Needs some more tweaking. * Added a lot of test code for template stuff (still needs some cases to be tested) * Removed the isTemplateParameterType from DataType, since it shouldn't be needed * Function qualTypeToDataType uses clang PrintingPolicy to fetch the desired format. * Merged a lot of code for getting the correct names and name hierarchies of definitions * Removed TokenComponentDataType * Merged both of the Storage::addTypeEdge(...) functions * Added "-fno-delayed-template-parsing" flag to parser for parsing test code.
This commit is contained in:
@@ -132,15 +132,4 @@ public:
|
||||
|
||||
private:
|
||||
int m_importantInt;
|
||||
};
|
||||
|
||||
class AnotherClass
|
||||
: public A
|
||||
{
|
||||
public:
|
||||
int publicInt;
|
||||
protected:
|
||||
int protectedInt;
|
||||
private:
|
||||
int privateInt;
|
||||
};
|
||||
};
|
||||
@@ -1,22 +1,4 @@
|
||||
ConfigManager.cpp ERROR: value path/to/nowhere is not present in config.
|
||||
Token.cpp ERROR: Location Id was not referenced by this Token.
|
||||
Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class
|
||||
Edge.cpp ERROR: Nodes are not plain copies.
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
Storage.cpp INFO: method: A::getCount <input.cc 8:13 8:20>
|
||||
Storage.cpp INFO: global usage: A::getCount -> A::count <input.cc 10:10 10:14>
|
||||
Storage.cpp INFO: method: A::process <input.cc 14:15 14:21>
|
||||
Storage.cpp INFO: field: A::count <input.cc 17:13 17:17>
|
||||
Storage.cpp INFO: class: B <input.cc 20:7 20:7>
|
||||
Storage.cpp INFO: inheritance: B : A <input.cc 21:4 21:11>
|
||||
Storage.cpp INFO: method: B::process <input.cc 24:15 24:21>
|
||||
Storage.cpp INFO: type usage: B::process -> int <input.cc 26:3 26:5>
|
||||
Storage.cpp INFO: function: main <input.cc 30:5 30:8>
|
||||
Storage.cpp INFO: type usage: main -> B <input.cc 32:2 32:2>
|
||||
Storage.cpp INFO: call: main -> B::B <input.cc 32:4 32:4>
|
||||
Storage.cpp INFO: call: main -> A::getCount <input.cc 34:9 34:21>
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
@@ -49,6 +31,24 @@ SearchMatch.cpp INFO:
|
||||
237 A::A
|
||||
^^^^
|
||||
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
Storage.cpp INFO: method: A::getCount <input.cc 8:13 8:20>
|
||||
Storage.cpp INFO: global usage: A::getCount -> A::count <input.cc 10:10 10:14>
|
||||
Storage.cpp INFO: method: A::process <input.cc 14:15 14:21>
|
||||
Storage.cpp INFO: field: A::count <input.cc 17:13 17:17>
|
||||
Storage.cpp INFO: class: B <input.cc 20:7 20:7>
|
||||
Storage.cpp INFO: inheritance: B : A <input.cc 21:4 21:11>
|
||||
Storage.cpp INFO: method: B::process <input.cc 24:15 24:21>
|
||||
Storage.cpp INFO: type usage: B::process -> int <input.cc 26:3 26:5>
|
||||
Storage.cpp INFO: function: main <input.cc 30:5 30:8>
|
||||
Storage.cpp INFO: type usage: main -> B <input.cc 32:2 32:2>
|
||||
Storage.cpp INFO: call: main -> B::B <input.cc 32:4 32:4>
|
||||
Storage.cpp INFO: call: main -> A::getCount <input.cc 34:9 34:21>
|
||||
Token.cpp ERROR: Location Id was not referenced by this Token.
|
||||
Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class
|
||||
Edge.cpp ERROR: Nodes are not plain copies.
|
||||
Settings.cpp WARNING: File for Settings not found.
|
||||
ConfigManager.cpp ERROR: value Bool is not present in config.
|
||||
ConfigManager.cpp ERROR: value Int is not present in config.
|
||||
@@ -64,6 +64,7 @@ ConfigManager.cpp ERROR: value Int is not present in config.
|
||||
ConfigManager.cpp ERROR: value Float is not present in config.
|
||||
ConfigManager.cpp ERROR: value String is not present in config.
|
||||
ConfigManager.cpp ERROR: value NewBool is not present in config.
|
||||
Graph.cpp ERROR: Can't remove member edge, without removing the child node.
|
||||
Storage.cpp INFO: typedef: type -> int <file.cpp 1:1 1:1>
|
||||
Storage.cpp INFO: class: Class <file.cpp 1:1 1:1>
|
||||
Storage.cpp INFO: struct: Struct <file.cpp 1:1 1:1>
|
||||
@@ -103,7 +104,6 @@ Storage.cpp INFO: global usage: isTrue -> global <file.cpp 1:7 1:7>
|
||||
Storage.cpp INFO: function: isTrue <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: struct: Struct <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: type usage: isTrue -> Struct <file.cpp 1:0 1: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 3 > 2
|
||||
TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8
|
||||
TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8
|
||||
|
||||
@@ -283,6 +283,7 @@ void QtGraphNode::setStyle()
|
||||
case Node::NODE_CLASS:
|
||||
case Node::NODE_ENUM:
|
||||
case Node::NODE_TYPEDEF:
|
||||
case Node::NODE_TEMPLATE_PARAMETER_TYPE:
|
||||
if (m_isHovering)
|
||||
{
|
||||
m_rect->setShadow(QColor(0, 0, 0, 255), 5);
|
||||
|
||||
@@ -89,8 +89,6 @@ add_files(
|
||||
data/graph/token_component/TokenComponentAccess.h
|
||||
data/graph/token_component/TokenComponentConst.cpp
|
||||
data/graph/token_component/TokenComponentConst.h
|
||||
data/graph/token_component/TokenComponentDataType.cpp
|
||||
data/graph/token_component/TokenComponentDataType.h
|
||||
data/graph/token_component/TokenComponentName.cpp
|
||||
data/graph/token_component/TokenComponentName.h
|
||||
data/graph/token_component/TokenComponentSignature.cpp
|
||||
|
||||
+74
-20
@@ -5,7 +5,6 @@
|
||||
|
||||
#include "data/graph/filter/GraphFilterConductor.h"
|
||||
#include "data/graph/token_component/TokenComponentConst.h"
|
||||
#include "data/graph/token_component/TokenComponentDataType.h"
|
||||
#include "data/graph/token_component/TokenComponentName.h"
|
||||
#include "data/graph/token_component/TokenComponentStatic.h"
|
||||
#include "data/graph/SubGraph.h"
|
||||
@@ -323,6 +322,77 @@ Id Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& f
|
||||
return edge->getId();
|
||||
}
|
||||
|
||||
Id Storage::onTemplateRecordParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||
const std::vector<std::string>& templateRecordNameHierarchy
|
||||
)
|
||||
{
|
||||
log("class template type parameter", templateParameterTypeName, location);
|
||||
std::vector<std::string> templateParameterTypeNameHierarchy = templateRecordNameHierarchy;
|
||||
templateParameterTypeNameHierarchy.back() += "::" + templateParameterTypeName;
|
||||
Node* templateParameterNode = addNodeHierarchy(Node::NODE_TEMPLATE_PARAMETER_TYPE, templateParameterTypeNameHierarchy);
|
||||
addTokenLocation(templateParameterNode, location);
|
||||
|
||||
Node* templateRecordNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateRecordNameHierarchy);
|
||||
|
||||
Edge* edge = m_graph.createEdge(Edge::EDGE_TEMPLATE_PARAMETER_OF, templateParameterNode, templateRecordNode);
|
||||
//addTokenLocation(edge, location);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Id Storage::onTemplateRecordSpecializationParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
||||
const RecordType specializedRecordType, const std::vector<std::string>& templateRecordNameHierarchy)
|
||||
{
|
||||
log("class template specialization", utility::join(specializedRecordNameHierarchy, "::") + " -> " + utility::join(templateRecordNameHierarchy, "::"), location);
|
||||
|
||||
Node::NodeType specializedRecordNodeType = Node::NODE_CLASS;
|
||||
if (specializedRecordType == ParserClient::RECORD_STRUCT)
|
||||
{
|
||||
specializedRecordNodeType = Node::NODE_STRUCT;
|
||||
}
|
||||
|
||||
Node* specializedRecordNode = addNodeHierarchy(specializedRecordNodeType, specializedRecordNameHierarchy);
|
||||
Node* templateRecordNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateRecordNameHierarchy);
|
||||
Edge* edge = m_graph.createEdge(Edge::EDGE_TEMPLATE_SPECIALIZATION_OF, specializedRecordNode, templateRecordNode);
|
||||
//addTokenLocation(edge, location);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Id Storage::onTemplateFunctionParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName, const ParseFunction function
|
||||
)
|
||||
{
|
||||
log("function template type parameter", templateParameterTypeName, location);
|
||||
|
||||
std::vector<std::string> templateParameterTypeNameHierarchy;
|
||||
templateParameterTypeNameHierarchy.push_back(function.getFullName() + "::"+ templateParameterTypeName);
|
||||
Node* templateParameterNode = addNodeHierarchy(Node::NODE_TEMPLATE_PARAMETER_TYPE, templateParameterTypeNameHierarchy);
|
||||
addTokenLocation(templateParameterNode, location);
|
||||
|
||||
Node* templateFunctionNode = addNodeHierarchyWithDistinctSignature(Node::NODE_UNDEFINED_FUNCTION, function);
|
||||
|
||||
Edge* edge = m_graph.createEdge(Edge::EDGE_TEMPLATE_PARAMETER_OF, templateParameterNode, templateFunctionNode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Id Storage::onTemplateFunctionSpecializationParsed(
|
||||
const ParseLocation& location, const ParseFunction specializedFunction, const ParseFunction templateFunction
|
||||
)
|
||||
{
|
||||
log("function template specialization", specializedFunction.getFullName(), location);
|
||||
|
||||
Node* specializedFunctionNode = addNodeHierarchyWithDistinctSignature(Node::NODE_UNDEFINED_FUNCTION, specializedFunction);
|
||||
Node* templateFunctionNode = addNodeHierarchyWithDistinctSignature(Node::NODE_UNDEFINED_FUNCTION, templateFunction);
|
||||
Edge* edge = m_graph.createEdge(Edge::EDGE_TEMPLATE_SPECIALIZATION_OF, specializedFunctionNode, templateFunctionNode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Id Storage::getIdForNodeWithName(const std::string& fullName) const
|
||||
{
|
||||
SearchNode* node = m_tokenIndex.getNode(fullName);
|
||||
@@ -685,23 +755,6 @@ TokenComponentAbstraction* Storage::addAbstraction(Node* node, ParserClient::Abs
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Edge* Storage::addTypeEdge(Node* node, Edge::EdgeType edgeType, const DataType& type)
|
||||
{
|
||||
Node* typeNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, utility::splitToVector(type.getRawTypeName(), "::")); // TODO: do we really need to split here?
|
||||
Edge* edge = m_graph.createEdge(edgeType, node, typeNode);
|
||||
|
||||
// FIXME: When a function uses the same type multiple times then we still only use one edge to save this,
|
||||
// but we can't store multiple DataTypes on this edge at the moment.
|
||||
if (!edge->getComponent<TokenComponentDataType>())
|
||||
{
|
||||
edge->addComponentDataType(
|
||||
std::make_shared<TokenComponentDataType>(type.getQualifierList(), type.getModifierStack())
|
||||
);
|
||||
}
|
||||
|
||||
return edge;
|
||||
}
|
||||
|
||||
Edge* Storage::addTypeEdge(Node* node, Edge::EdgeType edgeType, const ParseTypeUsage& typeUsage)
|
||||
{
|
||||
if (!typeUsage.location.isValid())
|
||||
@@ -709,9 +762,10 @@ Edge* Storage::addTypeEdge(Node* node, Edge::EdgeType edgeType, const ParseTypeU
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Edge* edge = addTypeEdge(node, edgeType, typeUsage.dataType);
|
||||
|
||||
Node* typeNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, typeUsage.dataType.getTypeNameHierarchy());
|
||||
Edge* edge = m_graph.createEdge(edgeType, node, typeNode);
|
||||
addTokenLocation(edge, typeUsage.location);
|
||||
|
||||
return edge;
|
||||
}
|
||||
|
||||
|
||||
+11
-2
@@ -68,6 +68,17 @@ public:
|
||||
const ParseLocation& location, const ParseFunction& user, const std::vector<std::string>& usedNameHierarchy);
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function);
|
||||
|
||||
virtual Id onTemplateRecordParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||
const std::vector<std::string>& templateRecordNameHierarchy);
|
||||
virtual Id onTemplateRecordSpecializationParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
||||
const RecordType specializedRecordType, const std::vector<std::string>& templateRecordNameHierarchy);
|
||||
virtual Id onTemplateFunctionParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName, const ParseFunction function);
|
||||
virtual Id onTemplateFunctionSpecializationParsed(
|
||||
const ParseLocation& location, const ParseFunction specializedFunction, const ParseFunction templateFunction);
|
||||
|
||||
// GraphAccess implementation
|
||||
virtual Id getIdForNodeWithName(const std::string& fullName) const;
|
||||
virtual std::string getNameForNodeWithId(Id id) const;
|
||||
@@ -96,7 +107,6 @@ protected:
|
||||
private:
|
||||
Node* addNodeHierarchy(Node::NodeType type, std::vector<std::string> nameHierarchy);
|
||||
|
||||
Node* addNodeHierarchy(Node::NodeType type, const std::string& fullName);
|
||||
Node* addNodeHierarchyWithDistinctSignature(Node::NodeType type, const ParseFunction& function);
|
||||
|
||||
TokenComponentAccess::AccessType convertAccessType(ParserClient::AccessType access) const;
|
||||
@@ -105,7 +115,6 @@ private:
|
||||
TokenComponentAbstraction::AbstractionType convertAbstractionType(ParserClient::AbstractionType abstraction) const;
|
||||
TokenComponentAbstraction* addAbstraction(Node* node, ParserClient::AbstractionType abstraction);
|
||||
|
||||
Edge* addTypeEdge(Node* node, Edge::EdgeType edgeType, const DataType& type);
|
||||
Edge* addTypeEdge(Node* node, Edge::EdgeType edgeType, const ParseTypeUsage& typeUsage);
|
||||
TokenLocation* addTokenLocation(Token* token, const ParseLocation& location, bool isScope = false);
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "data/graph/Node.h"
|
||||
#include "data/graph/token_component/TokenComponentAccess.h"
|
||||
#include "data/graph/token_component/TokenComponentDataType.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
Edge::Edge(EdgeType type, Node* from, Node* to)
|
||||
@@ -93,24 +92,6 @@ void Edge::addComponentAccess(std::shared_ptr<TokenComponentAccess> component)
|
||||
}
|
||||
}
|
||||
|
||||
void Edge::addComponentDataType(std::shared_ptr<TokenComponentDataType> component)
|
||||
{
|
||||
if (getComponent<TokenComponentDataType>())
|
||||
{
|
||||
LOG_ERROR("TokenComponentDataType has been set before!");
|
||||
}
|
||||
else if (m_type != EDGE_TYPEDEF_OF && m_type != EDGE_TYPE_OF &&
|
||||
m_type != EDGE_RETURN_TYPE_OF && m_type != EDGE_PARAMETER_TYPE_OF &&
|
||||
m_type != EDGE_TYPE_USAGE)
|
||||
{
|
||||
LOG_ERROR("TokenComponentDataType can't be set on edge of type: " + getTypeString());
|
||||
}
|
||||
else
|
||||
{
|
||||
addComponent(component);
|
||||
}
|
||||
}
|
||||
|
||||
std::string Edge::getTypeString(EdgeType type) const
|
||||
{
|
||||
switch (type)
|
||||
@@ -133,6 +114,10 @@ std::string Edge::getTypeString(EdgeType type) const
|
||||
return "usage";
|
||||
case EDGE_TYPEDEF_OF:
|
||||
return "typedef";
|
||||
case EDGE_TEMPLATE_PARAMETER_OF:
|
||||
return "template parameter";
|
||||
case EDGE_TEMPLATE_SPECIALIZATION_OF:
|
||||
return "template specialization";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
+11
-10
@@ -16,15 +16,17 @@ public:
|
||||
typedef int EdgeTypeMask;
|
||||
enum EdgeType : EdgeTypeMask
|
||||
{
|
||||
EDGE_MEMBER = 0x1,
|
||||
EDGE_TYPE_OF = 0x2,
|
||||
EDGE_RETURN_TYPE_OF = 0x4,
|
||||
EDGE_PARAMETER_TYPE_OF = 0x8,
|
||||
EDGE_TYPE_USAGE = 0x10,
|
||||
EDGE_USAGE = 0x20,
|
||||
EDGE_CALL = 0x40,
|
||||
EDGE_INHERITANCE = 0x80,
|
||||
EDGE_TYPEDEF_OF = 0x100
|
||||
EDGE_MEMBER = 0x1,
|
||||
EDGE_TYPE_OF = 0x2,
|
||||
EDGE_RETURN_TYPE_OF = 0x4,
|
||||
EDGE_PARAMETER_TYPE_OF = 0x8,
|
||||
EDGE_TYPE_USAGE = 0x10,
|
||||
EDGE_USAGE = 0x20,
|
||||
EDGE_CALL = 0x40,
|
||||
EDGE_INHERITANCE = 0x80,
|
||||
EDGE_TYPEDEF_OF = 0x100,
|
||||
EDGE_TEMPLATE_PARAMETER_OF = 0x200,
|
||||
EDGE_TEMPLATE_SPECIALIZATION_OF = 0x400
|
||||
};
|
||||
|
||||
Edge(EdgeType type, Node* from, Node* to);
|
||||
@@ -45,7 +47,6 @@ public:
|
||||
|
||||
// Component setters
|
||||
void addComponentAccess(std::shared_ptr<TokenComponentAccess> component);
|
||||
void addComponentDataType(std::shared_ptr<TokenComponentDataType> component);
|
||||
|
||||
// Logging.
|
||||
std::string getTypeString(EdgeType type) const;
|
||||
|
||||
@@ -313,6 +313,8 @@ std::string Node::getTypeString(NodeType type) const
|
||||
return "enum";
|
||||
case NODE_TYPEDEF:
|
||||
return "typedef";
|
||||
case NODE_TEMPLATE_PARAMETER_TYPE:
|
||||
return "template parameter type";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
+15
-13
@@ -19,21 +19,23 @@ class Node: public Token
|
||||
{
|
||||
public:
|
||||
typedef int NodeTypeMask;
|
||||
// list undefined types first to ensure that they get replaced by their defined counterparts when it is parsed.
|
||||
enum NodeType : NodeTypeMask
|
||||
{
|
||||
NODE_UNDEFINED = 0x1,
|
||||
NODE_UNDEFINED_FUNCTION = 0x2,
|
||||
NODE_UNDEFINED_VARIABLE = 0x4,
|
||||
NODE_UNDEFINED_TYPE = 0x8,
|
||||
NODE_STRUCT = 0x10,
|
||||
NODE_CLASS = 0x20,
|
||||
NODE_GLOBAL_VARIABLE = 0x40,
|
||||
NODE_FIELD = 0x80,
|
||||
NODE_FUNCTION = 0x100,
|
||||
NODE_METHOD = 0x200,
|
||||
NODE_NAMESPACE = 0x400,
|
||||
NODE_ENUM = 0x800,
|
||||
NODE_TYPEDEF = 0x1000
|
||||
NODE_UNDEFINED = 0x1,
|
||||
NODE_UNDEFINED_FUNCTION = 0x2,
|
||||
NODE_UNDEFINED_VARIABLE = 0x4,
|
||||
NODE_UNDEFINED_TYPE = 0x8,
|
||||
NODE_STRUCT = 0x10,
|
||||
NODE_CLASS = 0x20,
|
||||
NODE_GLOBAL_VARIABLE = 0x40,
|
||||
NODE_FIELD = 0x80,
|
||||
NODE_FUNCTION = 0x100,
|
||||
NODE_METHOD = 0x200,
|
||||
NODE_NAMESPACE = 0x400,
|
||||
NODE_ENUM = 0x800,
|
||||
NODE_TYPEDEF = 0x1000,
|
||||
NODE_TEMPLATE_PARAMETER_TYPE = 0x2000
|
||||
};
|
||||
|
||||
Node(NodeType type, const std::string& name);
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "data/graph/token_component/TokenComponentAbstraction.h"
|
||||
#include "data/graph/token_component/TokenComponentAccess.h"
|
||||
#include "data/graph/token_component/TokenComponentConst.h"
|
||||
#include "data/graph/token_component/TokenComponentDataType.h"
|
||||
#include "data/graph/token_component/TokenComponentStatic.h"
|
||||
|
||||
/*
|
||||
@@ -87,18 +86,7 @@ protected:
|
||||
{
|
||||
addNode(node);
|
||||
}
|
||||
|
||||
Edge* edge = node->findEdgeOfType(Edge::EDGE_TYPE_OF);
|
||||
if (!edge)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TokenComponentDataType* type = edge->getComponent<TokenComponentDataType>();
|
||||
if (type && type->isConstQualified())
|
||||
{
|
||||
addNode(node);
|
||||
}
|
||||
// TODO: add const component to field and variable nodes..
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
#include "data/graph/token_component/TokenComponentDataType.h"
|
||||
|
||||
#include "data/type/DataType.h"
|
||||
|
||||
TokenComponentDataType::TokenComponentDataType(
|
||||
const DataTypeQualifierList qualifierList, const DataTypeModifierStack modifierStack
|
||||
)
|
||||
: m_qualifierList(qualifierList)
|
||||
, m_modifierStack(modifierStack)
|
||||
{
|
||||
}
|
||||
|
||||
TokenComponentDataType::~TokenComponentDataType()
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<TokenComponent> TokenComponentDataType::copy() const
|
||||
{
|
||||
return std::make_shared<TokenComponentDataType>(*this);
|
||||
}
|
||||
|
||||
DataType TokenComponentDataType::getDataType(const std::string& typeName) const
|
||||
{
|
||||
return DataType(typeName, m_qualifierList, m_modifierStack);
|
||||
}
|
||||
|
||||
std::string TokenComponentDataType::getQualifiedTypeName(const std::string& typeName) const
|
||||
{
|
||||
return m_modifierStack.applyTo(m_qualifierList.applyTo(typeName));
|
||||
}
|
||||
|
||||
bool TokenComponentDataType::isConstQualified() const
|
||||
{
|
||||
return m_qualifierList.hasQualifier(DataTypeQualifierList::QUALIFIER_CONST);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
#ifndef TOKEN_COMPONENT_DATA_TYPE_H
|
||||
#define TOKEN_COMPONENT_DATA_TYPE_H
|
||||
|
||||
#include "data/graph/token_component/TokenComponent.h"
|
||||
#include "data/type/DataTypeModifierStack.h"
|
||||
#include "data/type/DataTypeQualifierList.h"
|
||||
|
||||
class DataType;
|
||||
|
||||
class TokenComponentDataType
|
||||
: public TokenComponent
|
||||
{
|
||||
public:
|
||||
TokenComponentDataType(const DataTypeQualifierList qualifierList, const DataTypeModifierStack modifierStack);
|
||||
virtual ~TokenComponentDataType();
|
||||
|
||||
virtual std::shared_ptr<TokenComponent> copy() const;
|
||||
|
||||
DataType getDataType(const std::string& typeName) const;
|
||||
std::string getQualifiedTypeName(const std::string& typeName) const;
|
||||
|
||||
bool isConstQualified() const;
|
||||
|
||||
private:
|
||||
const DataTypeQualifierList m_qualifierList;
|
||||
const DataTypeModifierStack m_modifierStack;
|
||||
};
|
||||
|
||||
#endif // TOKEN_COMPONENT_DATA_TYPE_H
|
||||
@@ -28,6 +28,11 @@ public:
|
||||
ABSTRACTION_NONE
|
||||
};
|
||||
|
||||
enum RecordType {
|
||||
RECORD_STRUCT,
|
||||
RECORD_CLASS
|
||||
};
|
||||
|
||||
static std::string addAccessPrefix(const std::string& str, AccessType access);
|
||||
static std::string addAbstractionPrefix(const std::string& str, AbstractionType abstraction);
|
||||
static std::string addStaticPrefix(const std::string& str, bool isStatic);
|
||||
@@ -84,6 +89,18 @@ public:
|
||||
virtual Id onGlobalVariableUsageParsed(
|
||||
const ParseLocation& location, const ParseFunction& user, const std::vector<std::string>& usedNameHierarchy) = 0;
|
||||
virtual Id onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& function) = 0;
|
||||
|
||||
virtual Id onTemplateRecordParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||
const std::vector<std::string>& templateRecordNameHierarchy) = 0;
|
||||
virtual Id onTemplateRecordSpecializationParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
||||
const RecordType specializedRecordType, const std::vector<std::string>& templateRecordNameHierarchy) = 0;
|
||||
virtual Id onTemplateFunctionParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||
const ParseFunction function) = 0;
|
||||
virtual Id onTemplateFunctionSpecializationParsed(
|
||||
const ParseLocation& location, const ParseFunction specializedFunction, const ParseFunction templateFunction) = 0;
|
||||
};
|
||||
|
||||
#endif // PARSER_CLIENT_H
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "data/parser/ParseTypeUsage.h"
|
||||
#include "data/parser/ParseVariable.h"
|
||||
#include "data/type/DataType.h"
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/utilityString.h"
|
||||
|
||||
ASTVisitor::ASTVisitor(clang::ASTContext* context, ParserClient* client)
|
||||
@@ -32,7 +33,7 @@ bool ASTVisitor::VisitTypedefDecl(clang::TypedefDecl* declaration)
|
||||
{
|
||||
m_client->onTypedefParsed(
|
||||
getParseLocationForNamedDecl(declaration),
|
||||
utility::splitToVector(declaration->getQualifiedNameAsString(), "::"),
|
||||
utility::getDeclNameHierarchy(declaration),
|
||||
getParseTypeUsage(declaration->getTypeSourceInfo()->getTypeLoc(), declaration->getUnderlyingType()),
|
||||
convertAccessType(declaration->getAccess())
|
||||
);
|
||||
@@ -49,19 +50,19 @@ bool ASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* declaration)
|
||||
{
|
||||
m_client->onClassParsed(
|
||||
getParseLocationForNamedDecl(declaration),
|
||||
utility::splitToVector(declaration->getQualifiedNameAsString(), "::"),
|
||||
utility::getDeclNameHierarchy(declaration),
|
||||
convertAccessType(declaration->getAccess()),
|
||||
getParseLocationOfRecordBody(declaration)
|
||||
);
|
||||
|
||||
if (declaration->hasDefinition() && declaration->getNumBases())
|
||||
{
|
||||
for (const auto& it : declaration->bases())
|
||||
for (const clang::CXXBaseSpecifier& it : declaration->bases())
|
||||
{
|
||||
m_client->onInheritanceParsed(
|
||||
getParseLocation(it.getSourceRange()),
|
||||
utility::splitToVector(declaration->getQualifiedNameAsString(), "::"),
|
||||
utility::splitToVector(getTypeName(it.getType()), "::"),
|
||||
utility::getDeclNameHierarchy(declaration),
|
||||
utility::qualTypeToDataType(it.getType()).getTypeNameHierarchy(),
|
||||
convertAccessType(it.getAccessSpecifier())
|
||||
);
|
||||
}
|
||||
@@ -71,10 +72,11 @@ bool ASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* declaration)
|
||||
{
|
||||
m_client->onStructParsed(
|
||||
getParseLocationForNamedDecl(declaration),
|
||||
utility::splitToVector(declaration->getQualifiedNameAsString(), "::"),
|
||||
utility::getDeclNameHierarchy(declaration),
|
||||
convertAccessType(declaration->getAccess()),
|
||||
getParseLocationOfRecordBody(declaration)
|
||||
);
|
||||
// TODO: what about struct inheritance?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +183,7 @@ bool ASTVisitor::VisitCXXMethodDecl(clang::CXXMethodDecl* declaration)
|
||||
getParseLocationOfFunctionBody(declaration)
|
||||
);
|
||||
|
||||
if (declaration->hasBody() && declaration->isThisDeclarationADefinition())
|
||||
if (declaration->hasBody() && declaration->getBody() != NULL && declaration->isThisDeclarationADefinition())
|
||||
{
|
||||
ASTBodyVisitor bodyVisitor(this, declaration);
|
||||
bodyVisitor.Visit(declaration->getBody());
|
||||
@@ -206,7 +208,7 @@ bool ASTVisitor::VisitCXXConstructorDecl(clang::CXXConstructorDecl* declaration)
|
||||
m_client->onFieldUsageParsed(
|
||||
getParseLocationForNamedDecl(init->getMember(), init->getMemberLocation()),
|
||||
getParseFunction(declaration),
|
||||
utility::splitToVector(init->getMember()->getQualifiedNameAsString(), "::")
|
||||
utility::getDeclNameHierarchy(init->getMember())
|
||||
);
|
||||
}
|
||||
else if (init->isBaseInitializer())
|
||||
@@ -222,7 +224,6 @@ bool ASTVisitor::VisitCXXConstructorDecl(clang::CXXConstructorDecl* declaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -232,11 +233,10 @@ bool ASTVisitor::VisitNamespaceDecl(clang::NamespaceDecl* declaration)
|
||||
{
|
||||
m_client->onNamespaceParsed(
|
||||
declaration->isAnonymousNamespace() ? ParseLocation() : getParseLocationForNamedDecl(declaration),
|
||||
utility::splitToVector(declaration->getQualifiedNameAsString(), "::"),
|
||||
utility::getDeclNameHierarchy(declaration),
|
||||
getParseLocation(declaration->getSourceRange())
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -246,12 +246,11 @@ bool ASTVisitor::VisitEnumDecl(clang::EnumDecl* declaration)
|
||||
{
|
||||
m_client->onEnumParsed(
|
||||
getParseLocationForNamedDecl(declaration),
|
||||
utility::splitToVector(declaration->getQualifiedNameAsString(), "::"),
|
||||
utility::getDeclNameHierarchy(declaration),
|
||||
convertAccessType(declaration->getAccess()),
|
||||
getParseLocation(declaration->getSourceRange())
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -261,13 +260,110 @@ bool ASTVisitor::VisitEnumConstantDecl(clang::EnumConstantDecl* declaration)
|
||||
{
|
||||
m_client->onEnumFieldParsed(
|
||||
getParseLocation(declaration->getSourceRange()),
|
||||
utility::splitToVector(declaration->getQualifiedNameAsString(), "::")
|
||||
utility::getDeclNameHierarchy(declaration)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
|
||||
{
|
||||
std::vector<std::string> templateRecordNameHierarchy = utility::getDeclNameHierarchy(declaration);
|
||||
|
||||
clang::TemplateParameterList* parameterList = declaration->getTemplateParameters();
|
||||
for (int i = 0; i < parameterList->size(); i++)
|
||||
{
|
||||
clang::NamedDecl* namedDecl = parameterList->getParam(i);
|
||||
|
||||
if (hasValidLocation(namedDecl))
|
||||
{
|
||||
std::string templateParameterTypeName = namedDecl->getNameAsString();
|
||||
|
||||
m_client->onTemplateRecordParameterTypeParsed(
|
||||
getParseLocationForNamedDecl(namedDecl),
|
||||
templateParameterTypeName,
|
||||
templateRecordNameHierarchy
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (clang::ClassTemplateDecl::spec_iterator it = declaration->specializations().begin(); // template argument as parameter does not work
|
||||
it != declaration->specializations().end(); it++
|
||||
)
|
||||
{
|
||||
ParserClient::RecordType specializedRecordType = it->isStruct() ? ParserClient::RECORD_STRUCT : ParserClient::RECORD_CLASS;
|
||||
std::vector<std::string> specializedRecordNameHierarchy = utility::getDeclNameHierarchy(*(it));
|
||||
m_client->onTemplateRecordSpecializationParsed(
|
||||
getParseLocationForNamedDecl(*it), specializedRecordNameHierarchy, specializedRecordType, templateRecordNameHierarchy
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* declaration)
|
||||
{
|
||||
//std::vector<std::string> templateRecordNameHierarchy = utility::splitToVector(
|
||||
// declaration->getQualifiedNameAsString(), "::"
|
||||
//);
|
||||
|
||||
//clang::ClassTemplateDecl* baseTemplateDecl = declaration->getSpecializedTemplate();
|
||||
|
||||
//std::string specializedParameterNamePart = "<";
|
||||
//const clang::TemplateArgumentList& templateArgumentList = declaration->getTemplateArgs();
|
||||
//for (int i = 0; i < templateArgumentList.size(); i++)
|
||||
//{
|
||||
// DataType datatype = utility::qualTypeToDataType(templateArgumentList.get(i).getAsType());
|
||||
// if (datatype.isTemplateParameterType())
|
||||
// {
|
||||
// specializedParameterNamePart += baseTemplateDecl->getTemplateParameters()->getParam(i)->getNameAsString();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// specializedParameterNamePart += datatype.getFullTypeName();
|
||||
// }
|
||||
// specializedParameterNamePart += (i < templateArgumentList.size() - 1) ? ", " : "";
|
||||
//}
|
||||
//specializedParameterNamePart += ">";
|
||||
|
||||
//int foo = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ASTVisitor::VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declaration)
|
||||
{
|
||||
const ParseFunction templateFunction = getParseFunction(declaration->getTemplatedDecl());
|
||||
for (clang::FunctionTemplateDecl::spec_iterator it = declaration->specializations().begin(); it != declaration->specializations().end(); it++)
|
||||
{
|
||||
ParseLocation specializedFunctionLocation = getParseLocationForNamedDecl(*(it));
|
||||
ParseFunction specializedFunction = getParseFunction(*(it));
|
||||
m_client->onTemplateFunctionSpecializationParsed(
|
||||
specializedFunctionLocation,
|
||||
specializedFunction,
|
||||
templateFunction);
|
||||
|
||||
m_client->onFunctionParsed(specializedFunctionLocation, specializedFunction, getParseLocationOfFunctionBody(*(it)));
|
||||
}
|
||||
clang::TemplateParameterList* parameterList = declaration->getTemplateParameters();
|
||||
for (int i = 0; i < parameterList->size(); i++)
|
||||
{
|
||||
clang::NamedDecl* namedDecl = parameterList->getParam(i);
|
||||
|
||||
if (hasValidLocation(namedDecl))
|
||||
{
|
||||
std::string templateParameterTypeName = namedDecl->getNameAsString();
|
||||
|
||||
m_client->onTemplateFunctionParameterTypeParsed(
|
||||
getParseLocationForNamedDecl(namedDecl),
|
||||
templateParameterTypeName,
|
||||
templateFunction
|
||||
);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ASTVisitor::VisitCallExprInDeclBody(clang::FunctionDecl* decl, clang::CallExpr* expr)
|
||||
{
|
||||
// if (clang::FunctionDecl *CalleeDecl = CE->getDirectCallee())
|
||||
@@ -340,7 +436,7 @@ void ASTVisitor::VisitMemberExprInDeclBody(clang::FunctionDecl* decl, clang::Mem
|
||||
m_client->onFieldUsageParsed(
|
||||
parseLocation,
|
||||
getParseFunction(decl),
|
||||
utility::splitToVector(expr->getMemberDecl()->getQualifiedNameAsString(), "::")
|
||||
utility::getDeclNameHierarchy(expr->getMemberDecl())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -354,7 +450,7 @@ void ASTVisitor::VisitDeclRefExprInDeclBody(clang::FunctionDecl* decl, clang::De
|
||||
m_client->onGlobalVariableUsageParsed(
|
||||
parseLocation,
|
||||
getParseFunction(decl),
|
||||
utility::splitToVector(expr->getDecl()->getQualifiedNameAsString(), "::")
|
||||
utility::getDeclNameHierarchy(expr->getDecl())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -504,16 +600,21 @@ std::vector<ParseTypeUsage> ASTVisitor::getParameters(clang::FunctionDecl* decla
|
||||
|
||||
ParseVariable ASTVisitor::getParseVariable(clang::DeclaratorDecl* declaration) const
|
||||
{
|
||||
bool isStatic = false;
|
||||
bool isStatic;
|
||||
std::vector<std::string> hameHierarchy = utility::getDeclNameHierarchy(declaration);
|
||||
if (clang::isa<clang::VarDecl>(declaration))
|
||||
{
|
||||
clang::VarDecl* varDecl = clang::dyn_cast<clang::VarDecl>(declaration);
|
||||
isStatic = varDecl->isStaticDataMember() || varDecl->getStorageClass() == clang::SC_Static;
|
||||
}
|
||||
else if (clang::isa<clang::FieldDecl>(declaration))
|
||||
{
|
||||
isStatic = false; // fieldDecls cannot be static. If they are, they are treated as VarDecls
|
||||
}
|
||||
|
||||
return ParseVariable(
|
||||
getParseTypeUsage(declaration->getTypeSourceInfo()->getTypeLoc(), declaration->getType()),
|
||||
utility::splitToVector(declaration->getQualifiedNameAsString(), "::"),
|
||||
hameHierarchy,
|
||||
isStatic
|
||||
);
|
||||
}
|
||||
@@ -522,6 +623,7 @@ ParseFunction ASTVisitor::getParseFunction(clang::FunctionDecl* declaration) con
|
||||
{
|
||||
bool isStatic = false;
|
||||
bool isConst = false;
|
||||
|
||||
if (clang::isa<clang::CXXMethodDecl>(declaration))
|
||||
{
|
||||
clang::CXXMethodDecl* methodDecl = clang::dyn_cast<clang::CXXMethodDecl>(declaration);
|
||||
@@ -535,7 +637,7 @@ ParseFunction ASTVisitor::getParseFunction(clang::FunctionDecl* declaration) con
|
||||
|
||||
return ParseFunction(
|
||||
getParseTypeUsageOfReturnType(declaration),
|
||||
utility::splitToVector(declaration->getQualifiedNameAsString(), "::"),
|
||||
utility::getDeclNameHierarchy(declaration),
|
||||
getParameters(declaration),
|
||||
isStatic,
|
||||
isConst
|
||||
|
||||
@@ -16,11 +16,11 @@ public:
|
||||
virtual ~ASTVisitor();
|
||||
|
||||
// Left for debugging purposes. Uncomment to see a colored ast-dump of the parsed file.
|
||||
// virtual bool VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl)
|
||||
// {
|
||||
// decl->dump();
|
||||
// return true;
|
||||
// }
|
||||
//virtual bool VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl)
|
||||
//{
|
||||
// decl->dump();
|
||||
// return true;
|
||||
//}
|
||||
|
||||
// RecursiveASTVisitor implementation
|
||||
virtual bool VisitStmt(const clang::Stmt* statement); // avoid visiting
|
||||
@@ -36,6 +36,10 @@ public:
|
||||
virtual bool VisitEnumDecl(clang::EnumDecl* declaration); // enums
|
||||
virtual bool VisitEnumConstantDecl(clang::EnumConstantDecl* declaration); // enum fields
|
||||
|
||||
virtual bool VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration);
|
||||
virtual bool VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* declaration);
|
||||
virtual bool VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *declaration);
|
||||
|
||||
// ASTBodyVisitorClient implementation
|
||||
virtual void VisitCallExprInDeclBody(clang::FunctionDecl* decl, clang::CallExpr* expr); // calls
|
||||
virtual void VisitCallExprInDeclBody(clang::VarDecl* decl, clang::CallExpr* expr); // calls in initialization of global variables
|
||||
|
||||
@@ -26,6 +26,10 @@ void CxxParser::parseFiles(
|
||||
// verbose
|
||||
// args.push_back("-v");
|
||||
|
||||
// The option -fno-delayed-template-parsing signals that templates that there should
|
||||
// be AST elements for unused template functions as well.
|
||||
args.push_back("-fno-delayed-template-parsing");
|
||||
|
||||
// The option -c signals that no executable is built.
|
||||
args.push_back("-c");
|
||||
|
||||
@@ -72,5 +76,7 @@ void CxxParser::parseFiles(
|
||||
void CxxParser::parseFile(std::shared_ptr<TextAccess> textAccess)
|
||||
{
|
||||
ASTActionFactory actionFactory(m_client);
|
||||
clang::tooling::runToolOnCode(actionFactory.create(), textAccess->getText());
|
||||
std::vector<std::string> args;
|
||||
args.push_back("-fno-delayed-template-parsing");
|
||||
clang::tooling::runToolOnCodeWithArgs(actionFactory.create(), textAccess->getText(), args);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#include "data/parser/cxx/utilityCxx.h"
|
||||
|
||||
#include <clang/AST/PrettyPrinter.h>
|
||||
#include <clang/AST/DeclTemplate.h>
|
||||
#include <clang/AST/ASTContext.h>
|
||||
|
||||
#include "data/type/DataType.h"
|
||||
#include "data/type/modifier/DataTypeModifierArray.h"
|
||||
#include "data/type/modifier/DataTypeModifierPointer.h"
|
||||
@@ -7,12 +11,13 @@
|
||||
#include "data/type/DataTypeModifierStack.h"
|
||||
#include "data/type/DataTypeQualifierList.h"
|
||||
#include "utility/utilityString.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
namespace utility
|
||||
{
|
||||
DataType qualTypeToDataType(clang::QualType qualType)
|
||||
{
|
||||
std::string typeName;
|
||||
std::vector<std::string> typeNameHerarchy;
|
||||
DataTypeQualifierList qualifierList;
|
||||
DataTypeModifierStack modifierStack;
|
||||
|
||||
@@ -21,7 +26,7 @@ namespace utility
|
||||
const clang::Type* type = qualType.getTypePtr();
|
||||
if (type->getAs<clang::TypedefType>())
|
||||
{
|
||||
typeName = utility::substrAfter(qualType.getAsString(), ' ');
|
||||
typeNameHerarchy.push_back(utility::substrAfter(qualType.getAsString(), ' '));
|
||||
break;
|
||||
}
|
||||
else if (type->isPointerType())
|
||||
@@ -54,17 +59,35 @@ namespace utility
|
||||
|
||||
qualType = type->getPointeeType();
|
||||
}
|
||||
else if (type->isStructureOrClassType() || type->isEnumeralType())
|
||||
{
|
||||
// we are working on the string here to not lose the namespace information stored in the name.
|
||||
typeName = utility::substrAfter(qualType.getAsString(), ' ');
|
||||
|
||||
// typeName = qualType.getBaseTypeIdentifier()->getName(); // this one does not keep namespace information.
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
typeName = qualType.getUnqualifiedType().getAsString();
|
||||
const clang::Type* type = qualType.getUnqualifiedType().getTypePtr();
|
||||
|
||||
if (clang::isa<clang::TagType>(type))
|
||||
{
|
||||
typeNameHerarchy = getDeclNameHierarchy(clang::dyn_cast<clang::TagType>(type)->getDecl());
|
||||
}
|
||||
else
|
||||
{
|
||||
clang::PrintingPolicy pp = clang::PrintingPolicy(clang::LangOptions());
|
||||
pp.SuppressTagKeyword = true; // value "true": for a class A it prints "A" instead of "class A"
|
||||
pp.Bool = true; // value "true": prints bool type as "bool" instead of "_Bool"
|
||||
std::string typeName = qualType.getUnqualifiedType().getAsString(pp);
|
||||
|
||||
if (type->isTemplateTypeParmType())
|
||||
{
|
||||
clang::TemplateTypeParmDecl* templateTypeParmDecl = clang::dyn_cast<clang::TemplateTypeParmType>(qualType.getUnqualifiedType())->getDecl();
|
||||
if (templateTypeParmDecl)
|
||||
{
|
||||
typeNameHerarchy = getContextNameHierarchy(templateTypeParmDecl->getDeclContext());
|
||||
typeNameHerarchy.back() += "::" + typeName;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
typeNameHerarchy.push_back(typeName);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -73,12 +96,90 @@ namespace utility
|
||||
{
|
||||
qualifierList.addQualifier(DataTypeQualifierList::QUALIFIER_CONST);
|
||||
}
|
||||
return DataType(typeNameHerarchy, qualifierList, modifierStack);
|
||||
}
|
||||
|
||||
if (typeName == "_Bool")
|
||||
std::vector<std::string> getDeclNameHierarchy(clang::Decl* declaration)
|
||||
{
|
||||
std::string declName = "";
|
||||
|
||||
if (clang::isa<clang::NamedDecl>(declaration))
|
||||
{
|
||||
typeName = "bool";
|
||||
declName = getDeclName(clang::dyn_cast<clang::NamedDecl>(declaration));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("unhandled declaration type");
|
||||
}
|
||||
std::vector<std::string> contextNameHierarchy = getContextNameHierarchy(declaration->getDeclContext());
|
||||
contextNameHierarchy.push_back(declName);
|
||||
return contextNameHierarchy;
|
||||
}
|
||||
|
||||
std::vector<std::string> getContextNameHierarchy(clang::DeclContext* declContext)
|
||||
{
|
||||
std::vector<std::string> contextNameHierarchy;
|
||||
|
||||
clang::DeclContext* parentContext = declContext->getParent();
|
||||
if (parentContext)
|
||||
{
|
||||
contextNameHierarchy = getContextNameHierarchy(parentContext);
|
||||
}
|
||||
|
||||
return DataType(typeName, qualifierList, modifierStack);
|
||||
if (clang::isa<clang::NamedDecl>(declContext))
|
||||
{
|
||||
std::string declName = getDeclName(clang::dyn_cast<clang::NamedDecl>(declContext));
|
||||
if (declName != "")
|
||||
{
|
||||
contextNameHierarchy.push_back(declName);
|
||||
}
|
||||
}
|
||||
return contextNameHierarchy;
|
||||
}
|
||||
|
||||
std::string getDeclName(clang::NamedDecl* declaration)
|
||||
{
|
||||
std::string declName = declaration->getNameAsString();
|
||||
|
||||
if (clang::isa<clang::CXXRecordDecl>(declaration))
|
||||
{
|
||||
clang::ClassTemplateDecl* templateClassDeclaration = clang::dyn_cast<clang::CXXRecordDecl>(declaration)->getDescribedClassTemplate();
|
||||
if (templateClassDeclaration)
|
||||
{
|
||||
declName = getDeclName(templateClassDeclaration);
|
||||
}
|
||||
else if (clang::isa<clang::ClassTemplateSpecializationDecl>(declaration))
|
||||
{
|
||||
std::string specializedParameterNamePart = "<";
|
||||
const clang::TemplateArgumentList& templateArgumentList = clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(declaration)->getTemplateArgs();
|
||||
for (int i = 0; i < templateArgumentList.size(); i++)
|
||||
{
|
||||
DataType datatype = utility::qualTypeToDataType(templateArgumentList.get(i).getAsType());
|
||||
specializedParameterNamePart += datatype.getFullTypeName();
|
||||
specializedParameterNamePart += (i < templateArgumentList.size() - 1) ? ", " : "";
|
||||
}
|
||||
specializedParameterNamePart += ">";
|
||||
declName += specializedParameterNamePart;
|
||||
}
|
||||
}
|
||||
else if (clang::isa<clang::TemplateDecl>(declaration))
|
||||
{
|
||||
std::string templateParameterNamePart = "<";
|
||||
clang::TemplateParameterList* parameterList = clang::dyn_cast<clang::TemplateDecl>(declaration)->getTemplateParameters();
|
||||
for (int i = 0; i < parameterList->size(); i++)
|
||||
{
|
||||
clang::NamedDecl* namedDecl = parameterList->getParam(i);
|
||||
|
||||
templateParameterNamePart += namedDecl->getNameAsString();
|
||||
templateParameterNamePart += (i < parameterList->size() - 1) ? ", " : "";
|
||||
}
|
||||
templateParameterNamePart += ">";
|
||||
declName += templateParameterNamePart;
|
||||
}
|
||||
else if (clang::isa<clang::NamespaceDecl>(declaration) && clang::dyn_cast<clang::NamespaceDecl>(declaration)->isAnonymousNamespace())
|
||||
{
|
||||
declName = "(anonymous namespace)";
|
||||
}
|
||||
return declName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,21 @@
|
||||
#define UTILITY_CLANG_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
|
||||
class DataType;
|
||||
|
||||
namespace utility
|
||||
{
|
||||
DataType qualTypeToDataType(clang::QualType qualType);
|
||||
|
||||
std::vector<std::string> getDeclNameHierarchy(clang::Decl* declaration);
|
||||
std::vector<std::string> getContextNameHierarchy(clang::DeclContext* declaration);
|
||||
std::string getDeclName(clang::NamedDecl* declaration);
|
||||
}
|
||||
|
||||
#endif // UTILITY_CLANG_H
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
#include "data/type/DataType.h"
|
||||
|
||||
DataType::DataType(const std::string& typeName)
|
||||
: m_typeName(typeName)
|
||||
#include "utility/utilityString.h"
|
||||
|
||||
DataType::DataType(const std::vector<std::string>& typeNameHierarchy)
|
||||
: m_typeNameHierarchy(typeNameHierarchy)
|
||||
{
|
||||
}
|
||||
|
||||
DataType::DataType(const std::string& typeName, const DataTypeQualifierList& qualifierList)
|
||||
: m_typeName(typeName)
|
||||
DataType::DataType(const std::vector<std::string>& typeNameHierarchy, const DataTypeQualifierList& qualifierList)
|
||||
: m_typeNameHierarchy(typeNameHierarchy)
|
||||
, m_qualifierList(qualifierList)
|
||||
{
|
||||
}
|
||||
|
||||
DataType::DataType(
|
||||
const std::string& typeName, const DataTypeQualifierList& qualifierList, const DataTypeModifierStack& modifierStack
|
||||
const std::vector<std::string>& typeNameHierarchy, const DataTypeQualifierList& qualifierList,
|
||||
const DataTypeModifierStack& modifierStack
|
||||
)
|
||||
: m_typeName(typeName)
|
||||
: m_typeNameHierarchy(typeNameHierarchy)
|
||||
, m_qualifierList(qualifierList)
|
||||
, m_modifierStack(modifierStack)
|
||||
{
|
||||
@@ -36,10 +39,15 @@ DataTypeModifierStack DataType::getModifierStack() const
|
||||
|
||||
std::string DataType::getFullTypeName() const
|
||||
{
|
||||
return m_modifierStack.applyTo(m_qualifierList.applyTo(m_typeName));
|
||||
return m_modifierStack.applyTo(m_qualifierList.applyTo(getRawTypeName()));
|
||||
}
|
||||
|
||||
std::string DataType::getRawTypeName() const
|
||||
{
|
||||
return m_typeName;
|
||||
return utility::join(m_typeNameHierarchy, "::");
|
||||
}
|
||||
|
||||
std::vector<std::string> DataType::getTypeNameHierarchy() const
|
||||
{
|
||||
return m_typeNameHierarchy;
|
||||
}
|
||||
|
||||
@@ -10,10 +10,11 @@
|
||||
class DataType
|
||||
{
|
||||
public:
|
||||
DataType(const std::string& typeName);
|
||||
DataType(const std::string& typeName, const DataTypeQualifierList& qualifierList);
|
||||
DataType(const std::vector<std::string>& typeNameHierarchy);
|
||||
DataType(const std::vector<std::string>& typeNameHierarchy, const DataTypeQualifierList& qualifierList);
|
||||
DataType(
|
||||
const std::string& typeName, const DataTypeQualifierList& qualifierList, const DataTypeModifierStack& modifierStack
|
||||
const std::vector<std::string>& typeNameHierarchy, const DataTypeQualifierList& qualifierList,
|
||||
const DataTypeModifierStack& modifierStack
|
||||
);
|
||||
~DataType();
|
||||
|
||||
@@ -22,9 +23,10 @@ public:
|
||||
|
||||
std::string getFullTypeName() const;
|
||||
std::string getRawTypeName() const;
|
||||
std::vector<std::string> getTypeNameHierarchy() const;
|
||||
|
||||
private:
|
||||
const std::string m_typeName;
|
||||
const std::vector<std::string> m_typeNameHierarchy;
|
||||
const DataTypeQualifierList m_qualifierList;
|
||||
const DataTypeModifierStack m_modifierStack;
|
||||
};
|
||||
|
||||
@@ -324,7 +324,23 @@ public:
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->namespaces.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->namespaces[0], "(anonymous) <1:1 3:1>");
|
||||
TS_ASSERT_EQUALS(client->namespaces[0], "(anonymous namespace) <1:1 3:1>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_nested_named_namespace()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"namespace A\n"
|
||||
"{\n"
|
||||
" namespace B\n"
|
||||
" {\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->namespaces.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->namespaces[0], "A <1:1 <1:11 1:11> 6:1>");
|
||||
TS_ASSERT_EQUALS(client->namespaces[1], "A::B <3:2 <3:12 3:12> 5:2>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_enum_defined_in_global_namespace()
|
||||
@@ -722,7 +738,7 @@ public:
|
||||
|
||||
TS_ASSERT_EQUALS(client->calls.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->calls[0], "int main() -> void App::App() <9:6 9:6>");
|
||||
TS_ASSERT_EQUALS(client->calls[1], "int main() -> void App::App(class App const &) <10:6 10:14>");
|
||||
TS_ASSERT_EQUALS(client->calls[1], "int main() -> void App::App(App const &) <10:6 10:14>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_global_constructor_call()
|
||||
@@ -974,6 +990,289 @@ public:
|
||||
TS_ASSERT_EQUALS(client->typeUses[1], "void B::B() -> A <8:8 8:8>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void test_cxx_parser_finds_template_parameter_type_of_template_class()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<T>::T <1:20 1:20>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_parameter_type_of_template_class_with_multiple_parameters()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T, typename U>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "A<T, U>::T <1:20 1:20>");
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A<T, U>::U <1:32 1:32>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_correct_field_member_name_of_template_class_in_declaration()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" int foo;\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->fields.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->fields[0], "private int A<T>::foo <4:6 4:8>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_correct_field_member_type_of_template_class_in_declaration()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" T foo;\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->fields.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->fields[0], "private A<T>::T A<T>::foo <4:4 4:6>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_class_specialization_with_non_template_argument()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" T foo;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"A<int> a\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A<int> -> A<T> <2:7 2:7>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_class_inheritance_from_specialized_template_class()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" T foo;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"class B: public A<int>\n"
|
||||
"{\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->inheritances.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->inheritances[0], "B : public A<int> <7:10 7:22>");
|
||||
}
|
||||
|
||||
//void _____test_cxx_parser_finds_template_class_specialization_with_template_argument()
|
||||
//{
|
||||
// std::shared_ptr<TestParserClient> client = parseCode(
|
||||
// "template <typename T>\n"
|
||||
// "class A\n"
|
||||
// "{\n"
|
||||
// " T foo;\n"
|
||||
// "};\n"
|
||||
// "\n"
|
||||
// "template <typename U>\n"
|
||||
// "class B: public A<U>\n"
|
||||
// "{\n"
|
||||
// "};\n"
|
||||
// );
|
||||
|
||||
// TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||
// TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A<U> -> A<T> <2:7 2:7>");
|
||||
//}
|
||||
|
||||
void test_cxx_parser_finds_template_class_constructor_usage_of_field()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" A(): foo() {}\n"
|
||||
" T foo;\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->usages.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->usages[0], "void A<T>::A<T>() -> A<T>::foo <4:7 4:9>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_enum_definition_in_template_class()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" Enum TestType\n"
|
||||
" {\n"
|
||||
" TEST_ONE\n"
|
||||
" TEST_TWO\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->enums.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->enums[0], "private A<T>::TestType <4:2 <4:7 4:14> 8:2>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_enum_usage_in_template_class()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" Enum TestType\n"
|
||||
" {\n"
|
||||
" TEST_ONE,\n"
|
||||
" TEST_TWO\n"
|
||||
" };\n"
|
||||
" TestType foo;\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->fields.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->fields[0], "private A<T>::TestType A<T>::foo <9:11 9:13>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_enum_fields_in_template_class()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" Enum TestType\n"
|
||||
" {\n"
|
||||
" TEST_ONE,\n"
|
||||
" TEST_TWO\n"
|
||||
" };\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->enumFields.size(), 2);
|
||||
TS_ASSERT_EQUALS(client->enumFields[0], "A<T>::TestType::TEST_ONE <6:3 6:3>");
|
||||
TS_ASSERT_EQUALS(client->enumFields[1], "A<T>::TestType::TEST_TWO <7:3 7:3>");
|
||||
}
|
||||
|
||||
//void _____test_cxx_parser_finds_correct_field_member_type_of_nested_template_class_in_declaration()
|
||||
//{
|
||||
// std::shared_ptr<TestParserClient> client = parseCode(
|
||||
// "template <typename T>\n"
|
||||
// "class A\n"
|
||||
// "{\n"
|
||||
// " class B\n"
|
||||
// " {\n"
|
||||
// " T foo;\n"
|
||||
// " };\n"
|
||||
// "};\n"
|
||||
// );
|
||||
|
||||
// TS_ASSERT_EQUALS(client->fields.size(), 1);
|
||||
// TS_ASSERT_EQUALS(client->fields[0], "private A<T>::T A<T>::B::foo <4:4 4:6>");
|
||||
//}
|
||||
|
||||
void test_cxx_parser_finds_correct_method_member_name_of_template_class_in_declaration()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" int foo();\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->methods.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->methods[0], "private int A<T>::foo() <4:6 4:8>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_correct_method_member_return_type_of_template_class_in_declaration()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"class A\n"
|
||||
"{\n"
|
||||
" T foo();\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->methods.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->methods[0], "private A<T>::T A<T>::foo() <4:4 4:6>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_template_parameter_type_of_template_function()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"T test(T a)\n"
|
||||
"{\n"
|
||||
" return a;\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateParameterTypes[0], "test::T <1:20 1:20>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_implicit_specialization_of_template_function()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"T test(T a)\n"
|
||||
"{\n"
|
||||
" return a;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"int main()\n"
|
||||
"{\n"
|
||||
" return test(1);\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "test -> test <2:3 2:6>");
|
||||
}
|
||||
|
||||
void test_cxx_parser_finds_explicit_specialization_of_template_function()
|
||||
{
|
||||
std::shared_ptr<TestParserClient> client = parseCode(
|
||||
"template <typename T>\n"
|
||||
"T test(T a)\n"
|
||||
"{\n"
|
||||
" return a;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"template <>\n"
|
||||
"int test<int>(int a)\n"
|
||||
"{\n"
|
||||
" return a + a;\n"
|
||||
"};\n"
|
||||
);
|
||||
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "test -> test <8:5 8:8>");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void test_cxx_parser_parses_multiple_files()
|
||||
{
|
||||
TestParserClient client;
|
||||
@@ -1137,6 +1436,46 @@ private:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onTemplateRecordParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||
const std::vector<std::string>& templateRecordNameHierarchy)
|
||||
{
|
||||
templateParameterTypes.push_back(
|
||||
addLocationSuffix(utility::join(templateRecordNameHierarchy, "::") + "::" + templateParameterTypeName, location)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onTemplateRecordSpecializationParsed(
|
||||
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
||||
const RecordType specializedRecordType, const std::vector<std::string>& templateRecordNameHierarchy)
|
||||
{
|
||||
templateSpecializations.push_back(
|
||||
addLocationSuffix(std::string(specializedRecordType == ParserClient::RECORD_CLASS ? "class" : "struct") + " " +
|
||||
utility::join(specializedRecordNameHierarchy, "::") + " -> " + utility::join(templateRecordNameHierarchy, "::"), location)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onTemplateFunctionParameterTypeParsed(
|
||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||
const ParseFunction function)
|
||||
{
|
||||
templateParameterTypes.push_back(
|
||||
addLocationSuffix(function.getFullName() + "::" + templateParameterTypeName, location)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Id onTemplateFunctionSpecializationParsed(
|
||||
const ParseLocation& location, const ParseFunction specializedFunction, const ParseFunction templateFunction)
|
||||
{
|
||||
templateSpecializations.push_back(
|
||||
addLocationSuffix(specializedFunction.getFullName() + " -> " + templateFunction.getFullName(), location)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<std::string> typedefs;
|
||||
std::vector<std::string> classes;
|
||||
std::vector<std::string> enums;
|
||||
@@ -1150,8 +1489,10 @@ private:
|
||||
|
||||
std::vector<std::string> inheritances;
|
||||
std::vector<std::string> calls;
|
||||
std::vector<std::string> usages;
|
||||
std::vector<std::string> typeUses;
|
||||
std::vector<std::string> usages; // for variables
|
||||
std::vector<std::string> typeUses; // for types
|
||||
std::vector<std::string> templateParameterTypes;
|
||||
std::vector<std::string> templateSpecializations;
|
||||
|
||||
private:
|
||||
void addTypeUse(const ParseTypeUsage& use)
|
||||
|
||||
@@ -10,14 +10,14 @@ class DataTypeTestSuite: public CxxTest::TestSuite
|
||||
public:
|
||||
void test_datatype_created_with_name_has_no_qualifiers_or_modifiers()
|
||||
{
|
||||
DataType dataType("int");
|
||||
DataType dataType(utility::splitToVector("int", "::"));
|
||||
TS_ASSERT_EQUALS("int", dataType.getFullTypeName());
|
||||
}
|
||||
|
||||
void test_datatype_created_with_name_and_empty_qualifiers_has_no_qualifiers_or_modifiers()
|
||||
{
|
||||
DataTypeQualifierList qualifierList;
|
||||
DataType dataType("int", qualifierList);
|
||||
DataType dataType(utility::splitToVector("int", "::"), qualifierList);
|
||||
TS_ASSERT_EQUALS("int", dataType.getFullTypeName());
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
{
|
||||
DataTypeQualifierList qualifierList;
|
||||
qualifierList.addQualifier(DataTypeQualifierList::QUALIFIER_CONST);
|
||||
DataType dataType("int", qualifierList);
|
||||
DataType dataType(utility::splitToVector("int", "::"), qualifierList);
|
||||
TS_ASSERT_EQUALS("int const", dataType.getFullTypeName());
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
{
|
||||
DataTypeQualifierList qualifierList;
|
||||
DataTypeModifierStack modifierStack;
|
||||
DataType dataType("int", qualifierList, modifierStack);
|
||||
DataType dataType(utility::splitToVector("int", "::"), qualifierList, modifierStack);
|
||||
TS_ASSERT_EQUALS("int", dataType.getFullTypeName());
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
DataTypeQualifierList qualifierList;
|
||||
DataTypeModifierStack modifierStack;
|
||||
modifierStack.push(std::make_shared<DataTypeModifierArray>());
|
||||
DataType dataType("int", qualifierList, modifierStack);
|
||||
DataType dataType(utility::splitToVector("int", "::"), qualifierList, modifierStack);
|
||||
TS_ASSERT_EQUALS("int []", dataType.getFullTypeName());
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
DataTypeQualifierList qualifierList;
|
||||
DataTypeModifierStack modifierStack;
|
||||
modifierStack.push(std::make_shared<DataTypeModifierPointer>());
|
||||
DataType dataType("int", qualifierList, modifierStack);
|
||||
DataType dataType(utility::splitToVector("int", "::"), qualifierList, modifierStack);
|
||||
TS_ASSERT_EQUALS("int *", dataType.getFullTypeName());
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
DataTypeQualifierList qualifierList;
|
||||
DataTypeModifierStack modifierStack;
|
||||
modifierStack.push(std::make_shared<DataTypeModifierReference>());
|
||||
DataType dataType("int", qualifierList, modifierStack);
|
||||
DataType dataType(utility::splitToVector("int", "::"), qualifierList, modifierStack);
|
||||
TS_ASSERT_EQUALS("int &", dataType.getFullTypeName());
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
std::shared_ptr<DataTypeModifier> modifier = std::make_shared<DataTypeModifierPointer>();
|
||||
modifier->addQualifier(DataTypeQualifierList::QUALIFIER_CONST);
|
||||
modifierStack.push(modifier);
|
||||
DataType dataType("int", qualifierList, modifierStack);
|
||||
DataType dataType(utility::splitToVector("int", "::"), qualifierList, modifierStack);
|
||||
TS_ASSERT_EQUALS("int * const", dataType.getFullTypeName());
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
DataTypeModifierStack modifierStack;
|
||||
modifierStack.push(std::make_shared<DataTypeModifierPointer>());
|
||||
modifierStack.push(std::make_shared<DataTypeModifierPointer>());
|
||||
DataType dataType("int", qualifierList, modifierStack);
|
||||
DataType dataType(utility::splitToVector("int", "::"), qualifierList, modifierStack);
|
||||
TS_ASSERT_EQUALS("int * *", dataType.getFullTypeName());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -560,7 +560,7 @@ private:
|
||||
|
||||
ParseTypeUsage typeUsage(const std::string& typeName) const
|
||||
{
|
||||
return ParseTypeUsage(validLocation(), DataType(typeName));
|
||||
return ParseTypeUsage(validLocation(), DataType(utility::splitToVector(typeName, "::")));
|
||||
}
|
||||
|
||||
std::vector<ParseTypeUsage> parameters(const std::string& param) const
|
||||
|
||||
Reference in New Issue
Block a user