data: parse partial template specializations
* fixed: implicit template specializations will be found even if the original template definition is located in a different file (that gets included). * implemented correct extraction of template parameters, template arguments and template specialization edges. * added token locations for template parameters of partial template specializations. * graph view displays full names of template parameters and template arguments. * added test code for features
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
template <typename T, typename U>
|
||||||
|
class TemplateTestClass
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class TemplateTestClass<int, T>
|
||||||
|
{
|
||||||
|
int foo;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class TemplateTestClass<float, float>
|
||||||
|
{
|
||||||
|
int foo;
|
||||||
|
};
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#include "header.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
TemplateTestClass<int, int> t2;
|
||||||
|
// TemplateTestClass<float, float> t3;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -388,25 +388,38 @@ Id Storage::onTemplateRecordParameterTypeParsed(
|
|||||||
const std::vector<std::string>& templateRecordNameHierarchy
|
const std::vector<std::string>& templateRecordNameHierarchy
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
log("class template type parameter", templateParameterTypeName, location);
|
log("template record type parameter", templateParameterTypeName, location);
|
||||||
std::vector<std::string> templateParameterTypeNameHierarchy = templateRecordNameHierarchy;
|
std::vector<std::string> templateParameterTypeNameHierarchy = templateRecordNameHierarchy;
|
||||||
templateParameterTypeNameHierarchy.back() += "::" + templateParameterTypeName;
|
templateParameterTypeNameHierarchy.back() += "::" + templateParameterTypeName;
|
||||||
Node* templateParameterNode = addNodeHierarchy(Node::NODE_TEMPLATE_PARAMETER_TYPE, templateParameterTypeNameHierarchy);
|
Node* templateParameterNode = addNodeHierarchy(Node::NODE_TEMPLATE_PARAMETER_TYPE, templateParameterTypeNameHierarchy);
|
||||||
addTokenLocation(templateParameterNode, location);
|
addTokenLocation(templateParameterNode, location);
|
||||||
|
|
||||||
Node* templateRecordNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateRecordNameHierarchy);
|
Node* templateRecordNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateRecordNameHierarchy);
|
||||||
|
|
||||||
Edge* edge = m_graph.createEdge(Edge::EDGE_TEMPLATE_PARAMETER_OF, templateParameterNode, templateRecordNode);
|
Edge* edge = m_graph.createEdge(Edge::EDGE_TEMPLATE_PARAMETER_OF, templateParameterNode, templateRecordNode);
|
||||||
//addTokenLocation(edge, location);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Id Storage::onTemplateRecordArgumentTypeParsed(
|
||||||
|
const ParseLocation& location, const std::vector<std::string>& templateArgumentTypeNameHierarchy,
|
||||||
|
const std::vector<std::string>& templateRecordNameHierarchy)
|
||||||
|
{
|
||||||
|
log("template record argument", utility::join(templateArgumentTypeNameHierarchy, "::") + " -> " + utility::join(templateRecordNameHierarchy, "::"), location);
|
||||||
|
Node* templateArgumentNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateArgumentTypeNameHierarchy);
|
||||||
|
Node* templateRecordNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateRecordNameHierarchy);
|
||||||
|
Edge* edge = m_graph.createEdge(Edge::EDGE_TEMPLATE_ARGUMENT_OF, templateArgumentNode, templateRecordNode);
|
||||||
|
if (location.isValid())
|
||||||
|
{
|
||||||
|
addTokenLocation(templateArgumentNode, location);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Id Storage::onTemplateRecordSpecializationParsed(
|
Id Storage::onTemplateRecordSpecializationParsed(
|
||||||
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
||||||
const RecordType specializedRecordType, const std::vector<std::string>& templateRecordNameHierarchy)
|
const RecordType specializedRecordType, const std::vector<std::string>& specializedFromNameHierarchy)
|
||||||
{
|
{
|
||||||
log("class template specialization", utility::join(specializedRecordNameHierarchy, "::") + " -> " + utility::join(templateRecordNameHierarchy, "::"), location);
|
log("template record specialization", utility::join(specializedRecordNameHierarchy, "::") + " -> " + utility::join(specializedFromNameHierarchy, "::"), location);
|
||||||
|
|
||||||
Node::NodeType specializedRecordNodeType = Node::NODE_CLASS;
|
Node::NodeType specializedRecordNodeType = Node::NODE_CLASS;
|
||||||
if (specializedRecordType == ParserClient::RECORD_STRUCT)
|
if (specializedRecordType == ParserClient::RECORD_STRUCT)
|
||||||
@@ -415,7 +428,7 @@ Id Storage::onTemplateRecordSpecializationParsed(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Node* specializedRecordNode = addNodeHierarchy(specializedRecordNodeType, specializedRecordNameHierarchy);
|
Node* specializedRecordNode = addNodeHierarchy(specializedRecordNodeType, specializedRecordNameHierarchy);
|
||||||
Node* templateRecordNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, templateRecordNameHierarchy);
|
Node* templateRecordNode = addNodeHierarchy(Node::NODE_UNDEFINED_TYPE, specializedFromNameHierarchy);
|
||||||
|
|
||||||
Edge* edge = m_graph.createEdge(Edge::EDGE_TEMPLATE_SPECIALIZATION_OF, specializedRecordNode, templateRecordNode);
|
Edge* edge = m_graph.createEdge(Edge::EDGE_TEMPLATE_SPECIALIZATION_OF, specializedRecordNode, templateRecordNode);
|
||||||
//addTokenLocation(edge, location);
|
//addTokenLocation(edge, location);
|
||||||
@@ -555,7 +568,7 @@ std::shared_ptr<Graph> Storage::getGraphForActiveTokenIds(const std::vector<Id>&
|
|||||||
else if (tokenIds.size() == 1)
|
else if (tokenIds.size() == 1)
|
||||||
{
|
{
|
||||||
Token* token = m_graph.getTokenById(tokenIds[0]);
|
Token* token = m_graph.getTokenById(tokenIds[0]);
|
||||||
|
|
||||||
if (!token)
|
if (!token)
|
||||||
{
|
{
|
||||||
LOG_ERROR_STREAM(<< "Token with id " << tokenIds[0] << " was not found");
|
LOG_ERROR_STREAM(<< "Token with id " << tokenIds[0] << " was not found");
|
||||||
|
|||||||
@@ -83,9 +83,14 @@ public:
|
|||||||
virtual Id onTemplateRecordParameterTypeParsed(
|
virtual Id onTemplateRecordParameterTypeParsed(
|
||||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||||
const std::vector<std::string>& templateRecordNameHierarchy);
|
const std::vector<std::string>& templateRecordNameHierarchy);
|
||||||
|
virtual Id onTemplateRecordArgumentTypeParsed(
|
||||||
|
const ParseLocation& location, const std::vector<std::string>& templateArgumentTypeNameHierarchy,
|
||||||
|
const std::vector<std::string>& templateRecordNameHierarchy);
|
||||||
|
|
||||||
virtual Id onTemplateRecordSpecializationParsed(
|
virtual Id onTemplateRecordSpecializationParsed(
|
||||||
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
||||||
const RecordType specializedRecordType, const std::vector<std::string>& templateRecordNameHierarchy);
|
const RecordType specializedRecordType, const std::vector<std::string>& specializedFromNameHierarchy);
|
||||||
|
|
||||||
virtual Id onTemplateFunctionParameterTypeParsed(
|
virtual Id onTemplateFunctionParameterTypeParsed(
|
||||||
const ParseLocation& location, const std::string& templateParameterTypeName, const ParseFunction function);
|
const ParseLocation& location, const std::string& templateParameterTypeName, const ParseFunction function);
|
||||||
virtual Id onTemplateFunctionSpecializationParsed(
|
virtual Id onTemplateFunctionSpecializationParsed(
|
||||||
|
|||||||
@@ -133,6 +133,8 @@ std::string Edge::getTypeString(EdgeType type) const
|
|||||||
return "typedef";
|
return "typedef";
|
||||||
case EDGE_TEMPLATE_PARAMETER_OF:
|
case EDGE_TEMPLATE_PARAMETER_OF:
|
||||||
return "template parameter";
|
return "template parameter";
|
||||||
|
case EDGE_TEMPLATE_ARGUMENT_OF:
|
||||||
|
return "template argument";
|
||||||
case EDGE_TEMPLATE_SPECIALIZATION_OF:
|
case EDGE_TEMPLATE_SPECIALIZATION_OF:
|
||||||
return "template specialization";
|
return "template specialization";
|
||||||
case EDGE_AGGREGATION:
|
case EDGE_AGGREGATION:
|
||||||
|
|||||||
@@ -27,9 +27,10 @@ public:
|
|||||||
EDGE_INHERITANCE = 0x80,
|
EDGE_INHERITANCE = 0x80,
|
||||||
EDGE_TYPEDEF_OF = 0x100,
|
EDGE_TYPEDEF_OF = 0x100,
|
||||||
EDGE_TEMPLATE_PARAMETER_OF = 0x200,
|
EDGE_TEMPLATE_PARAMETER_OF = 0x200,
|
||||||
EDGE_TEMPLATE_SPECIALIZATION_OF = 0x400,
|
EDGE_TEMPLATE_ARGUMENT_OF = 0x400,
|
||||||
|
EDGE_TEMPLATE_SPECIALIZATION_OF = 0x800,
|
||||||
|
|
||||||
EDGE_AGGREGATION = 0x800
|
EDGE_AGGREGATION = 0x1000
|
||||||
};
|
};
|
||||||
|
|
||||||
Edge(EdgeType type, Node* from, Node* to);
|
Edge(EdgeType type, Node* from, Node* to);
|
||||||
|
|||||||
@@ -9,12 +9,6 @@
|
|||||||
#include "data/graph/token_component/TokenComponentSignature.h"
|
#include "data/graph/token_component/TokenComponentSignature.h"
|
||||||
#include "utility/logging/logging.h"
|
#include "utility/logging/logging.h"
|
||||||
|
|
||||||
Node::Node(NodeType type, const std::string& name)
|
|
||||||
: m_type(type)
|
|
||||||
, m_nameComponent(std::make_shared<TokenComponentNameCached>(name))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Node::Node(NodeType type, std::shared_ptr<TokenComponentName> nameComponent)
|
Node::Node(NodeType type, std::shared_ptr<TokenComponentName> nameComponent)
|
||||||
: m_type(type)
|
: m_type(type)
|
||||||
, m_nameComponent(nameComponent)
|
, m_nameComponent(nameComponent)
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ public:
|
|||||||
NODE_TEMPLATE_PARAMETER_TYPE = 0x2000
|
NODE_TEMPLATE_PARAMETER_TYPE = 0x2000
|
||||||
};
|
};
|
||||||
|
|
||||||
Node(NodeType type, const std::string& name);
|
|
||||||
Node(NodeType type, std::shared_ptr<TokenComponentName> nameComponent);
|
Node(NodeType type, std::shared_ptr<TokenComponentName> nameComponent);
|
||||||
Node(const Node& other);
|
Node(const Node& other);
|
||||||
virtual ~Node();
|
virtual ~Node();
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ TokenComponentNameReferenced::~TokenComponentNameReferenced()
|
|||||||
|
|
||||||
std::shared_ptr<TokenComponent> TokenComponentNameReferenced::copy() const
|
std::shared_ptr<TokenComponent> TokenComponentNameReferenced::copy() const
|
||||||
{
|
{
|
||||||
return std::make_shared<TokenComponentNameCached>(getFullName());
|
return std::make_shared<TokenComponentNameCached>(m_searchNode->getNameHierarchy());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TokenComponentNameReferenced::getName() const
|
std::string TokenComponentNameReferenced::getName() const
|
||||||
@@ -47,8 +47,8 @@ const SearchNode* TokenComponentNameReferenced::getSearchNode() const
|
|||||||
return m_searchNode;
|
return m_searchNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenComponentNameCached::TokenComponentNameCached(const std::string& fullName)
|
TokenComponentNameCached::TokenComponentNameCached(const std::vector<std::string>& nameHierarchy)
|
||||||
: m_fullName(fullName)
|
: m_nameHierarchy(nameHierarchy)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,17 +58,17 @@ TokenComponentNameCached::~TokenComponentNameCached()
|
|||||||
|
|
||||||
std::shared_ptr<TokenComponent> TokenComponentNameCached::copy() const
|
std::shared_ptr<TokenComponent> TokenComponentNameCached::copy() const
|
||||||
{
|
{
|
||||||
return std::make_shared<TokenComponentNameCached>(m_fullName);
|
return std::make_shared<TokenComponentNameCached>(m_nameHierarchy);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TokenComponentNameCached::getName() const
|
std::string TokenComponentNameCached::getName() const
|
||||||
{
|
{
|
||||||
return utility::split(m_fullName, SearchIndex::DELIMITER).back();
|
return m_nameHierarchy.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TokenComponentNameCached::getFullName() const
|
std::string TokenComponentNameCached::getFullName() const
|
||||||
{
|
{
|
||||||
return m_fullName;
|
return utility::join(m_nameHierarchy, "::");
|
||||||
}
|
}
|
||||||
|
|
||||||
const SearchNode* TokenComponentNameCached::getSearchNode() const
|
const SearchNode* TokenComponentNameCached::getSearchNode() const
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class TokenComponentNameCached
|
|||||||
: public TokenComponentName
|
: public TokenComponentName
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TokenComponentNameCached(const std::string& fullName);
|
TokenComponentNameCached(const std::vector<std::string>& nameHierarchy);
|
||||||
virtual ~TokenComponentNameCached();
|
virtual ~TokenComponentNameCached();
|
||||||
|
|
||||||
virtual std::shared_ptr<TokenComponent> copy() const;
|
virtual std::shared_ptr<TokenComponent> copy() const;
|
||||||
@@ -56,7 +56,7 @@ public:
|
|||||||
virtual const SearchNode* getSearchNode() const;
|
virtual const SearchNode* getSearchNode() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string m_fullName;
|
const std::vector<std::string> m_nameHierarchy;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TOKEN_COMPONENT_NAME_H
|
#endif // TOKEN_COMPONENT_NAME_H
|
||||||
|
|||||||
@@ -100,9 +100,12 @@ public:
|
|||||||
virtual Id onTemplateRecordParameterTypeParsed(
|
virtual Id onTemplateRecordParameterTypeParsed(
|
||||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||||
const std::vector<std::string>& templateRecordNameHierarchy) = 0;
|
const std::vector<std::string>& templateRecordNameHierarchy) = 0;
|
||||||
|
virtual Id onTemplateRecordArgumentTypeParsed(
|
||||||
|
const ParseLocation& location, const std::vector<std::string>& templateArgumentTypeNameHierarchy,
|
||||||
|
const std::vector<std::string>& templateRecordNameHierarchy) = 0;
|
||||||
virtual Id onTemplateRecordSpecializationParsed(
|
virtual Id onTemplateRecordSpecializationParsed(
|
||||||
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
||||||
const RecordType specializedRecordType, const std::vector<std::string>& templateRecordNameHierarchy) = 0;
|
const RecordType specializedRecordType, const std::vector<std::string>& specializedFromNameHierarchy) = 0;
|
||||||
virtual Id onTemplateFunctionParameterTypeParsed(
|
virtual Id onTemplateFunctionParameterTypeParsed(
|
||||||
const ParseLocation& location, const std::string& templateParameterTypeName,
|
const ParseLocation& location, const std::string& templateParameterTypeName,
|
||||||
const ParseFunction function) = 0;
|
const ParseFunction function) = 0;
|
||||||
|
|||||||
@@ -275,36 +275,44 @@ bool ASTVisitor::VisitClassTemplateDecl(clang::ClassTemplateDecl* declaration)
|
|||||||
if (hasValidLocation(declaration))
|
if (hasValidLocation(declaration))
|
||||||
{
|
{
|
||||||
std::vector<std::string> templateRecordNameHierarchy = utility::getDeclNameHierarchy(declaration);
|
std::vector<std::string> templateRecordNameHierarchy = utility::getDeclNameHierarchy(declaration);
|
||||||
|
|
||||||
clang::TemplateParameterList* parameterList = declaration->getTemplateParameters();
|
clang::TemplateParameterList* parameterList = declaration->getTemplateParameters();
|
||||||
for (size_t i = 0; i < parameterList->size(); i++)
|
for (size_t i = 0; i < parameterList->size(); i++)
|
||||||
{
|
{
|
||||||
clang::NamedDecl* namedDecl = parameterList->getParam(i);
|
clang::NamedDecl* namedDecl = parameterList->getParam(i);
|
||||||
|
|
||||||
if (hasValidLocation(namedDecl))
|
if (hasValidLocation(namedDecl))
|
||||||
{
|
{
|
||||||
std::string templateParameterTypeName = namedDecl->getNameAsString();
|
|
||||||
|
|
||||||
m_client->onTemplateRecordParameterTypeParsed(
|
m_client->onTemplateRecordParameterTypeParsed(
|
||||||
getParseLocationForNamedDecl(namedDecl),
|
getParseLocationForNamedDecl(namedDecl),
|
||||||
templateParameterTypeName,
|
namedDecl->getNameAsString(),
|
||||||
templateRecordNameHierarchy
|
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for implicit template specializations we do not need a valid location of the original template class definition (since that file could be included)
|
||||||
|
// handles explicit specializations and implicit specializations but no explicit partial specializations
|
||||||
|
for (clang::ClassTemplateDecl::spec_iterator it = declaration->specializations().begin();
|
||||||
|
it != declaration->specializations().end(); it++
|
||||||
|
)
|
||||||
|
{
|
||||||
|
clang::ClassTemplateSpecializationDecl* specializationDecl = *it;
|
||||||
|
|
||||||
|
std::vector<std::string> specializationParentNameHierarchy = utility::getTemplateSpecializationParentNameHierarchy(specializationDecl);
|
||||||
|
|
||||||
|
ParserClient::RecordType specializedRecordType = specializationDecl->isStruct() ? ParserClient::RECORD_STRUCT : ParserClient::RECORD_CLASS;
|
||||||
|
std::vector<std::string> specializedRecordNameHierarchy = utility::getDeclNameHierarchy(specializationDecl);
|
||||||
|
m_client->onTemplateRecordSpecializationParsed(
|
||||||
|
getParseLocationForNamedDecl(*it), specializedRecordNameHierarchy, specializedRecordType, specializationParentNameHierarchy
|
||||||
|
);
|
||||||
|
|
||||||
|
const clang::TemplateArgumentList &argList = specializationDecl->getTemplateArgs();
|
||||||
|
for (int i = 0; i < argList.size(); i++)
|
||||||
|
{
|
||||||
|
std::vector<std::string> argumentNameHierarchy = utility::qualTypeToDataType(argList.get(i).getAsType()).getTypeNameHierarchy();
|
||||||
|
m_client->onTemplateRecordArgumentTypeParsed(ParseLocation(), argumentNameHierarchy, specializedRecordNameHierarchy); // TODO: What about the ParseLocation
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,32 +320,40 @@ bool ASTVisitor::VisitClassTemplatePartialSpecializationDecl(clang::ClassTemplat
|
|||||||
{
|
{
|
||||||
if (hasValidLocation(declaration))
|
if (hasValidLocation(declaration))
|
||||||
{
|
{
|
||||||
//std::vector<std::string> templateRecordNameHierarchy = utility::splitToVector(
|
std::vector<std::string> specializedRecordNameHierarchy = utility::getDeclNameHierarchy(declaration);
|
||||||
// declaration->getQualifiedNameAsString(), "::"
|
std::vector<std::string> specializationParentNameHierarchy = utility::getTemplateSpecializationParentNameHierarchy(declaration);
|
||||||
//);
|
|
||||||
|
|
||||||
//clang::ClassTemplateDecl* baseTemplateDecl = declaration->getSpecializedTemplate();
|
ParserClient::RecordType specializedRecordType = declaration->isStruct() ? ParserClient::RECORD_STRUCT : ParserClient::RECORD_CLASS;
|
||||||
|
m_client->onTemplateRecordSpecializationParsed(
|
||||||
|
getParseLocationForNamedDecl(declaration), specializedRecordNameHierarchy, specializedRecordType, specializationParentNameHierarchy
|
||||||
|
);
|
||||||
|
|
||||||
//std::string specializedParameterNamePart = "<";
|
clang::TemplateParameterList* parameterList = declaration->getTemplateParameters();
|
||||||
//const clang::TemplateArgumentList& templateArgumentList = declaration->getTemplateArgs();
|
for (size_t i = 0; i < parameterList->size(); i++)
|
||||||
//for (int i = 0; i < templateArgumentList.size(); i++)
|
{
|
||||||
//{
|
clang::NamedDecl* namedDecl = parameterList->getParam(i);
|
||||||
// DataType datatype = utility::qualTypeToDataType(templateArgumentList.get(i).getAsType());
|
if (hasValidLocation(namedDecl))
|
||||||
// if (datatype.isTemplateParameterType())
|
{
|
||||||
// {
|
m_client->onTemplateRecordParameterTypeParsed(
|
||||||
// specializedParameterNamePart += baseTemplateDecl->getTemplateParameters()->getParam(i)->getNameAsString();
|
getParseLocationForNamedDecl(namedDecl),
|
||||||
// }
|
namedDecl->getNameAsString(),
|
||||||
// else
|
specializedRecordNameHierarchy
|
||||||
// {
|
);
|
||||||
// specializedParameterNamePart += datatype.getFullTypeName();
|
}
|
||||||
// }
|
}
|
||||||
// specializedParameterNamePart += (i < templateArgumentList.size() - 1) ? ", " : "";
|
|
||||||
//}
|
|
||||||
//specializedParameterNamePart += ">";
|
|
||||||
|
|
||||||
//int foo = 0;
|
const clang::ASTTemplateArgumentListInfo* argumentInfoList = declaration->getTemplateArgsAsWritten();
|
||||||
|
for (int i = 0; i < argumentInfoList->NumTemplateArgs; i++)
|
||||||
|
{
|
||||||
|
const clang::TemplateArgumentLoc& argumentLoc = argumentInfoList->operator[](i);
|
||||||
|
const clang::QualType argumentType = argumentLoc.getArgument().getAsType();
|
||||||
|
|
||||||
|
m_client->onTemplateRecordArgumentTypeParsed(
|
||||||
|
getParseLocation(argumentLoc.getSourceRange()),
|
||||||
|
utility::qualTypeToDataType(argumentType).getTypeNameHierarchy(),
|
||||||
|
specializedRecordNameHierarchy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,18 +107,22 @@ namespace utility
|
|||||||
|
|
||||||
std::vector<std::string> getDeclNameHierarchy(clang::Decl* declaration)
|
std::vector<std::string> getDeclNameHierarchy(clang::Decl* declaration)
|
||||||
{
|
{
|
||||||
std::string declName = "";
|
std::vector<std::string> contextNameHierarchy;
|
||||||
|
if (declaration)
|
||||||
|
{
|
||||||
|
std::string declName = "";
|
||||||
|
|
||||||
if (clang::isa<clang::NamedDecl>(declaration))
|
if (clang::isa<clang::NamedDecl>(declaration))
|
||||||
{
|
{
|
||||||
declName = getDeclName(clang::dyn_cast<clang::NamedDecl>(declaration));
|
declName = getDeclName(clang::dyn_cast<clang::NamedDecl>(declaration));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR("unhandled declaration type");
|
||||||
|
}
|
||||||
|
contextNameHierarchy = getContextNameHierarchy(declaration->getDeclContext());
|
||||||
|
contextNameHierarchy.push_back(declName);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR("unhandled declaration type");
|
|
||||||
}
|
|
||||||
std::vector<std::string> contextNameHierarchy = getContextNameHierarchy(declaration->getDeclContext());
|
|
||||||
contextNameHierarchy.push_back(declName);
|
|
||||||
return contextNameHierarchy;
|
return contextNameHierarchy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +158,19 @@ namespace utility
|
|||||||
{
|
{
|
||||||
declName = getDeclName(templateClassDeclaration);
|
declName = getDeclName(templateClassDeclaration);
|
||||||
}
|
}
|
||||||
|
else if (clang::isa<clang::ClassTemplatePartialSpecializationDecl>(declaration))
|
||||||
|
{
|
||||||
|
int templateArgumentCount = clang::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(declaration)->getTemplateArgs().size();
|
||||||
|
const clang::ASTTemplateArgumentListInfo* templateArgumentListInfo = clang::dyn_cast<clang::ClassTemplatePartialSpecializationDecl>(declaration)->getTemplateArgsAsWritten();
|
||||||
|
std::string specializedParameterNamePart = "<";
|
||||||
|
for (int i = 0; i < templateArgumentCount; i++)
|
||||||
|
{
|
||||||
|
specializedParameterNamePart += templateArgumentListInfo->getTemplateArgs()[i].getArgument().getAsType().getAsString();
|
||||||
|
specializedParameterNamePart += (i < templateArgumentCount - 1) ? ", " : "";
|
||||||
|
}
|
||||||
|
specializedParameterNamePart += ">";
|
||||||
|
declName += specializedParameterNamePart;
|
||||||
|
}
|
||||||
else if (clang::isa<clang::ClassTemplateSpecializationDecl>(declaration))
|
else if (clang::isa<clang::ClassTemplateSpecializationDecl>(declaration))
|
||||||
{
|
{
|
||||||
std::string specializedParameterNamePart = "<";
|
std::string specializedParameterNamePart = "<";
|
||||||
@@ -188,4 +205,21 @@ namespace utility
|
|||||||
}
|
}
|
||||||
return declName;
|
return declName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> getTemplateSpecializationParentNameHierarchy(clang::ClassTemplateSpecializationDecl* declaration)
|
||||||
|
{
|
||||||
|
std::vector<std::string> specializationParentNameHierarchy;
|
||||||
|
llvm::PointerUnion<clang::ClassTemplateDecl*, clang::ClassTemplatePartialSpecializationDecl*> pu = declaration->getSpecializedTemplateOrPartial();
|
||||||
|
if (pu.is<clang::ClassTemplateDecl*>())
|
||||||
|
{
|
||||||
|
clang::ClassTemplateDecl* specializedFromDecl = pu.get<clang::ClassTemplateDecl*>();
|
||||||
|
specializationParentNameHierarchy = utility::getDeclNameHierarchy(specializedFromDecl);
|
||||||
|
}
|
||||||
|
else if (pu.is<clang::ClassTemplatePartialSpecializationDecl*>())
|
||||||
|
{
|
||||||
|
clang::ClassTemplatePartialSpecializationDecl* specializedFromDecl = pu.get<clang::ClassTemplatePartialSpecializationDecl*>();
|
||||||
|
specializationParentNameHierarchy = utility::getDeclNameHierarchy(specializedFromDecl);
|
||||||
|
}
|
||||||
|
return specializationParentNameHierarchy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "clang/AST/Type.h"
|
#include "clang/AST/Type.h"
|
||||||
#include "clang/AST/Decl.h"
|
#include "clang/AST/Decl.h"
|
||||||
|
#include "clang/AST/DeclTemplate.h"
|
||||||
|
|
||||||
class DataType;
|
class DataType;
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ namespace utility
|
|||||||
std::vector<std::string> getDeclNameHierarchy(clang::Decl* declaration);
|
std::vector<std::string> getDeclNameHierarchy(clang::Decl* declaration);
|
||||||
std::vector<std::string> getContextNameHierarchy(clang::DeclContext* declaration);
|
std::vector<std::string> getContextNameHierarchy(clang::DeclContext* declaration);
|
||||||
std::string getDeclName(clang::NamedDecl* declaration);
|
std::string getDeclName(clang::NamedDecl* declaration);
|
||||||
|
std::vector<std::string> getTemplateSpecializationParentNameHierarchy(clang::ClassTemplateSpecializationDecl* declaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // UTILITY_CLANG_H
|
#endif // UTILITY_CLANG_H
|
||||||
|
|||||||
@@ -24,6 +24,18 @@ const std::string& SearchNode::getName() const
|
|||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> SearchNode::getNameHierarchy() const
|
||||||
|
{
|
||||||
|
std::vector<std::string> nameHierarchy;
|
||||||
|
const SearchNode* parent = getParent();
|
||||||
|
if (parent)
|
||||||
|
{
|
||||||
|
nameHierarchy = parent->getNameHierarchy();
|
||||||
|
}
|
||||||
|
nameHierarchy.push_back(getName());
|
||||||
|
return nameHierarchy;
|
||||||
|
}
|
||||||
|
|
||||||
std::string SearchNode::getFullName() const
|
std::string SearchNode::getFullName() const
|
||||||
{
|
{
|
||||||
if (m_parent && m_parent->m_nameId)
|
if (m_parent && m_parent->m_nameId)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public:
|
|||||||
~SearchNode();
|
~SearchNode();
|
||||||
|
|
||||||
const std::string& getName() const;
|
const std::string& getName() const;
|
||||||
|
std::vector<std::string> getNameHierarchy() const;
|
||||||
std::string getFullName() const;
|
std::string getFullName() const;
|
||||||
|
|
||||||
Id getNameId() const;
|
Id getNameId() const;
|
||||||
|
|||||||
+154
-25
@@ -1134,6 +1134,105 @@ public:
|
|||||||
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A<T, U>::U <1:32 1:32>");
|
TS_ASSERT_EQUALS(client->templateParameterTypes[1], "A<T, U>::U <1:32 1:32>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_cxx_parser_finds_template_argument_of_implicit_template_specialization()
|
||||||
|
{
|
||||||
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
|
"template <typename T>\n"
|
||||||
|
"class A\n"
|
||||||
|
"{\n"
|
||||||
|
"};\n"
|
||||||
|
"int main()\n"
|
||||||
|
"{\n"
|
||||||
|
" A<int> a;\n"
|
||||||
|
" return 0;\n"
|
||||||
|
"}\n"
|
||||||
|
);
|
||||||
|
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||||
|
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<int>->int <0:0 0:0>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_cxx_parser_finds_explicit_template_specialization()
|
||||||
|
{
|
||||||
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
|
"template <typename T>\n"
|
||||||
|
"class A\n"
|
||||||
|
"{\n"
|
||||||
|
"};\n"
|
||||||
|
"template <>\n"
|
||||||
|
"class A<int>\n"
|
||||||
|
"{\n"
|
||||||
|
"};\n"
|
||||||
|
);
|
||||||
|
TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||||
|
TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A<int> -> A<T> <6:7 6:7>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_cxx_parser_finds_explicit_partial_template_specialization()
|
||||||
|
{
|
||||||
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
|
"template <typename T, typename U>\n"
|
||||||
|
"class A\n"
|
||||||
|
"{\n"
|
||||||
|
"};\n"
|
||||||
|
"template <typename T>\n"
|
||||||
|
"class A<T, int>\n"
|
||||||
|
"{\n"
|
||||||
|
"};\n"
|
||||||
|
);
|
||||||
|
TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||||
|
TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A<T, int> -> A<T, U> <6:7 6:7>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_cxx_parser_finds_argument_of_explicit_partial_template_specialization()
|
||||||
|
{
|
||||||
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
|
"template <typename T, typename U>\n"
|
||||||
|
"class A\n"
|
||||||
|
"{\n"
|
||||||
|
"};\n"
|
||||||
|
"template <typename T>\n"
|
||||||
|
"class A<T, int>\n"
|
||||||
|
"{\n"
|
||||||
|
"};\n"
|
||||||
|
);
|
||||||
|
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2);
|
||||||
|
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<T, int>->A<T, int>::T <6:9 6:9>");
|
||||||
|
TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<T, int>->int <6:12 6:12>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_cxx_parser_finds_correct_name_of_explicit_template_specialization()
|
||||||
|
{
|
||||||
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
|
"template <typename T, typename U>\n"
|
||||||
|
"class A\n"
|
||||||
|
"{\n"
|
||||||
|
"};\n"
|
||||||
|
"template <typename T>\n"
|
||||||
|
"class A<T, int>\n"
|
||||||
|
"{\n"
|
||||||
|
"};\n"
|
||||||
|
);
|
||||||
|
TS_ASSERT_EQUALS(client->classes.size(), 2);
|
||||||
|
TS_ASSERT_EQUALS(client->classes[0], "A<T, U> <2:1 <2:7 2:7> 4:1>");
|
||||||
|
TS_ASSERT_EQUALS(client->classes[1], "A<T, int> <5:1 <6:7 6:7> 8:1>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_cxx_parser_finds_argument_of_explicit_template_specialization()
|
||||||
|
{
|
||||||
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
|
"template <typename T>\n"
|
||||||
|
"class A\n"
|
||||||
|
"{\n"
|
||||||
|
"};\n"
|
||||||
|
"template <>\n"
|
||||||
|
"class A<int>\n"
|
||||||
|
"{\n"
|
||||||
|
"};\n"
|
||||||
|
);
|
||||||
|
TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1);
|
||||||
|
TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<int>->int <0:0 0:0>");
|
||||||
|
}
|
||||||
|
|
||||||
void test_cxx_parser_finds_correct_field_member_name_of_template_class_in_declaration()
|
void test_cxx_parser_finds_correct_field_member_name_of_template_class_in_declaration()
|
||||||
{
|
{
|
||||||
std::shared_ptr<TestParserClient> client = parseCode(
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
@@ -1148,7 +1247,7 @@ public:
|
|||||||
TS_ASSERT_EQUALS(client->fields[0], "private int A<T>::foo <4:6 4:8>");
|
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()
|
void test_cxx_parser_finds_correct_type_of_field_member_of_template_class_in_declaration()
|
||||||
{
|
{
|
||||||
std::shared_ptr<TestParserClient> client = parseCode(
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
"template <typename T>\n"
|
"template <typename T>\n"
|
||||||
@@ -1162,7 +1261,7 @@ public:
|
|||||||
TS_ASSERT_EQUALS(client->fields[0], "private A<T>::T A<T>::foo <4:4 4:6>");
|
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()
|
void test_cxx_parser_finds_implicit_template_class_specialization()
|
||||||
{
|
{
|
||||||
std::shared_ptr<TestParserClient> client = parseCode(
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
"template <typename T>\n"
|
"template <typename T>\n"
|
||||||
@@ -1178,7 +1277,7 @@ public:
|
|||||||
TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A<int> -> A<T> <2:7 2:7>");
|
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()
|
void test_cxx_parser_finds_class_inheritance_from_implicit_template_class_specialization()
|
||||||
{
|
{
|
||||||
std::shared_ptr<TestParserClient> client = parseCode(
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
"template <typename T>\n"
|
"template <typename T>\n"
|
||||||
@@ -1196,7 +1295,7 @@ public:
|
|||||||
TS_ASSERT_EQUALS(client->inheritances[0], "B : public A<int> <7:10 7:22>");
|
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()
|
//___void test_cxx_parser_finds_template_class_specialization_with_template_argument()
|
||||||
//{
|
//{
|
||||||
// std::shared_ptr<TestParserClient> client = parseCode(
|
// std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
// "template <typename T>\n"
|
// "template <typename T>\n"
|
||||||
@@ -1209,10 +1308,11 @@ public:
|
|||||||
// "class B: public A<U>\n"
|
// "class B: public A<U>\n"
|
||||||
// "{\n"
|
// "{\n"
|
||||||
// "};\n"
|
// "};\n"
|
||||||
|
// "B<int> bar;"
|
||||||
// );
|
// );
|
||||||
|
// int i = 0;
|
||||||
// TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
// //TS_ASSERT_EQUALS(client->templateSpecializations.size(), 1);
|
||||||
// TS_ASSERT_EQUALS(client->templateSpecializations[0], "class A<U> -> A<T> <2:7 2:7>");
|
// //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()
|
void test_cxx_parser_finds_template_class_constructor_usage_of_field()
|
||||||
@@ -1286,22 +1386,36 @@ public:
|
|||||||
TS_ASSERT_EQUALS(client->enumFields[1], "A<T>::TestType::TEST_TWO <7:3 7: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()
|
void test_cxx_parser_finds_correct_field_member_type_of_nested_template_class_in_declaration_____typedef()
|
||||||
//{
|
{
|
||||||
// std::shared_ptr<TestParserClient> client = parseCode(
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
// "template <typename T>\n"
|
"template <typename T>\n"
|
||||||
// "class A\n"
|
"class A\n"
|
||||||
// "{\n"
|
"{\n"
|
||||||
// " class B\n"
|
" typedef T TempType;"
|
||||||
// " {\n"
|
"};\n"
|
||||||
// " T foo;\n"
|
);
|
||||||
// " };\n"
|
|
||||||
// "};\n"
|
|
||||||
// );
|
|
||||||
|
|
||||||
// TS_ASSERT_EQUALS(client->fields.size(), 1);
|
TS_ASSERT_EQUALS(client->typedefs.size(), 1);
|
||||||
// TS_ASSERT_EQUALS(client->fields[0], "private A<T>::T A<T>::B::foo <4:4 4:6>");
|
TS_ASSERT_EQUALS(client->typedefs[0], "private A<T>::T -> A<T>::TempType <4:12 4:19>");
|
||||||
//}
|
}
|
||||||
|
|
||||||
|
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 <6:5 6:7>");
|
||||||
|
}
|
||||||
|
|
||||||
void test_cxx_parser_finds_correct_method_member_name_of_template_class_in_declaration()
|
void test_cxx_parser_finds_correct_method_member_name_of_template_class_in_declaration()
|
||||||
{
|
{
|
||||||
@@ -1317,7 +1431,7 @@ public:
|
|||||||
TS_ASSERT_EQUALS(client->methods[0], "private int A<T>::foo() <4:6 4:8>");
|
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()
|
void test_cxx_parser_finds_correct_method_return_type_of_template_class_in_declaration()
|
||||||
{
|
{
|
||||||
std::shared_ptr<TestParserClient> client = parseCode(
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
"template <typename T>\n"
|
"template <typename T>\n"
|
||||||
@@ -1331,6 +1445,10 @@ public:
|
|||||||
TS_ASSERT_EQUALS(client->methods[0], "private A<T>::T A<T>::foo() <4:4 4:6>");
|
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()
|
void test_cxx_parser_finds_template_parameter_type_of_template_function()
|
||||||
{
|
{
|
||||||
std::shared_ptr<TestParserClient> client = parseCode(
|
std::shared_ptr<TestParserClient> client = parseCode(
|
||||||
@@ -1597,13 +1715,23 @@ private:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual Id onTemplateRecordArgumentTypeParsed(
|
||||||
|
const ParseLocation& location, const std::vector<std::string>& templateArgumentTypeNameHierarchy,
|
||||||
|
const std::vector<std::string>& templateRecordNameHierarchy)
|
||||||
|
{
|
||||||
|
templateArgumentTypes.push_back(
|
||||||
|
addLocationSuffix(utility::join(templateRecordNameHierarchy, "::") + "->" + utility::join(templateArgumentTypeNameHierarchy, "::"), location)
|
||||||
|
);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
virtual Id onTemplateRecordSpecializationParsed(
|
virtual Id onTemplateRecordSpecializationParsed(
|
||||||
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
const ParseLocation& location, const std::vector<std::string>& specializedRecordNameHierarchy,
|
||||||
const RecordType specializedRecordType, const std::vector<std::string>& templateRecordNameHierarchy)
|
const RecordType specializedRecordType, const std::vector<std::string>& specializedFromNameHierarchy)
|
||||||
{
|
{
|
||||||
templateSpecializations.push_back(
|
templateSpecializations.push_back(
|
||||||
addLocationSuffix(std::string(specializedRecordType == ParserClient::RECORD_CLASS ? "class" : "struct") + " " +
|
addLocationSuffix(std::string(specializedRecordType == ParserClient::RECORD_CLASS ? "class" : "struct") + " " +
|
||||||
utility::join(specializedRecordNameHierarchy, "::") + " -> " + utility::join(templateRecordNameHierarchy, "::"), location)
|
utility::join(specializedRecordNameHierarchy, "::") + " -> " + utility::join(specializedFromNameHierarchy, "::"), location)
|
||||||
);
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1645,6 +1773,7 @@ private:
|
|||||||
std::vector<std::string> usages; // for variables
|
std::vector<std::string> usages; // for variables
|
||||||
std::vector<std::string> typeUses; // for types
|
std::vector<std::string> typeUses; // for types
|
||||||
std::vector<std::string> templateParameterTypes;
|
std::vector<std::string> templateParameterTypes;
|
||||||
|
std::vector<std::string> templateArgumentTypes;
|
||||||
std::vector<std::string> templateSpecializations;
|
std::vector<std::string> templateSpecializations;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
+28
-27
@@ -1,6 +1,7 @@
|
|||||||
#include "cxxtest/TestSuite.h"
|
#include "cxxtest/TestSuite.h"
|
||||||
|
|
||||||
#include "data/graph/Graph.h"
|
#include "data/graph/Graph.h"
|
||||||
|
#include "data/graph/token_component/TokenComponentName.h"
|
||||||
|
|
||||||
class GraphTestSuite : public CxxTest::TestSuite
|
class GraphTestSuite : public CxxTest::TestSuite
|
||||||
{
|
{
|
||||||
@@ -101,7 +102,7 @@ public:
|
|||||||
|
|
||||||
void test_nodes_are_nodes()
|
void test_nodes_are_nodes()
|
||||||
{
|
{
|
||||||
Node a(Node::NODE_UNDEFINED, "A");
|
Node a(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
|
|
||||||
TS_ASSERT(a.isNode());
|
TS_ASSERT(a.isNode());
|
||||||
TS_ASSERT(!a.isEdge());
|
TS_ASSERT(!a.isEdge());
|
||||||
@@ -109,8 +110,8 @@ public:
|
|||||||
|
|
||||||
void test_edges_are_edges()
|
void test_edges_are_edges()
|
||||||
{
|
{
|
||||||
Node a(Node::NODE_UNDEFINED, "A");
|
Node a(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
Node b(Node::NODE_UNDEFINED, "B");
|
Node b(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("B", "::")));
|
||||||
Edge e(Edge::EDGE_TYPE_OF, &a, &b);
|
Edge e(Edge::EDGE_TYPE_OF, &a, &b);
|
||||||
|
|
||||||
TS_ASSERT(!e.isNode());
|
TS_ASSERT(!e.isNode());
|
||||||
@@ -119,27 +120,27 @@ public:
|
|||||||
|
|
||||||
void test_set_type_of_node_from_constructor()
|
void test_set_type_of_node_from_constructor()
|
||||||
{
|
{
|
||||||
Node n(Node::NODE_FUNCTION, "A");
|
Node n(Node::NODE_FUNCTION, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
TS_ASSERT_EQUALS(Node::NODE_FUNCTION, n.getType());
|
TS_ASSERT_EQUALS(Node::NODE_FUNCTION, n.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_set_type_of_node_from_undefined()
|
void test_set_type_of_node_from_undefined()
|
||||||
{
|
{
|
||||||
Node n(Node::NODE_UNDEFINED, "A");
|
Node n(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
n.setType(Node::NODE_CLASS);
|
n.setType(Node::NODE_CLASS);
|
||||||
TS_ASSERT_EQUALS(Node::NODE_CLASS, n.getType());
|
TS_ASSERT_EQUALS(Node::NODE_CLASS, n.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_can_not_change_type_of_node_after_it_was_set()
|
void test_can_not_change_type_of_node_after_it_was_set()
|
||||||
{
|
{
|
||||||
Node n(Node::NODE_NAMESPACE, "A");
|
Node n(Node::NODE_NAMESPACE, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
n.setType(Node::NODE_CLASS);
|
n.setType(Node::NODE_CLASS);
|
||||||
TS_ASSERT_DIFFERS(Node::NODE_CLASS, n.getType());
|
TS_ASSERT_DIFFERS(Node::NODE_CLASS, n.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_node_can_be_copied_and_keeps_same_id()
|
void test_node_can_be_copied_and_keeps_same_id()
|
||||||
{
|
{
|
||||||
Node n(Node::NODE_NAMESPACE, "A");
|
Node n(Node::NODE_NAMESPACE, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
Node n2(n);
|
Node n2(n);
|
||||||
|
|
||||||
TS_ASSERT_DIFFERS(&n, &n2);
|
TS_ASSERT_DIFFERS(&n, &n2);
|
||||||
@@ -150,15 +151,15 @@ public:
|
|||||||
|
|
||||||
void test_node_type_bit_masking()
|
void test_node_type_bit_masking()
|
||||||
{
|
{
|
||||||
Node n(Node::NODE_NAMESPACE, "A");
|
Node n(Node::NODE_NAMESPACE, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
TS_ASSERT(n.isType(Node::NODE_FUNCTION | Node::NODE_NAMESPACE | Node::NODE_CLASS));
|
TS_ASSERT(n.isType(Node::NODE_FUNCTION | Node::NODE_NAMESPACE | Node::NODE_CLASS));
|
||||||
TS_ASSERT(!n.isType(Node::NODE_FUNCTION | Node::NODE_METHOD | Node::NODE_CLASS));
|
TS_ASSERT(!n.isType(Node::NODE_FUNCTION | Node::NODE_METHOD | Node::NODE_CLASS));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_get_type_of_edges()
|
void test_get_type_of_edges()
|
||||||
{
|
{
|
||||||
Node a(Node::NODE_UNDEFINED, "A");
|
Node a(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
Node b(Node::NODE_UNDEFINED, "B");
|
Node b(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("B", "::")));
|
||||||
Edge e(Edge::EDGE_TYPE_OF, &a, &b);
|
Edge e(Edge::EDGE_TYPE_OF, &a, &b);
|
||||||
|
|
||||||
TS_ASSERT_EQUALS(Edge::EDGE_TYPE_OF, e.getType());
|
TS_ASSERT_EQUALS(Edge::EDGE_TYPE_OF, e.getType());
|
||||||
@@ -166,8 +167,8 @@ public:
|
|||||||
|
|
||||||
void test_edge_can_be_copied_and_keeps_same_id()
|
void test_edge_can_be_copied_and_keeps_same_id()
|
||||||
{
|
{
|
||||||
Node a(Node::NODE_UNDEFINED, "A");
|
Node a(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
Node b(Node::NODE_UNDEFINED, "B");
|
Node b(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("B", "::")));
|
||||||
Edge e(Edge::EDGE_TYPE_OF, &a, &b);
|
Edge e(Edge::EDGE_TYPE_OF, &a, &b);
|
||||||
Edge e2(e, &a, &b);
|
Edge e2(e, &a, &b);
|
||||||
|
|
||||||
@@ -178,8 +179,8 @@ public:
|
|||||||
|
|
||||||
void test_edge_type_bit_masking()
|
void test_edge_type_bit_masking()
|
||||||
{
|
{
|
||||||
Node a(Node::NODE_UNDEFINED, "A");
|
Node a(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
Node b(Node::NODE_UNDEFINED, "B");
|
Node b(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("B", "::")));
|
||||||
Edge e(Edge::EDGE_TYPE_OF, &a, &b);
|
Edge e(Edge::EDGE_TYPE_OF, &a, &b);
|
||||||
|
|
||||||
TS_ASSERT(e.isType(Edge::EDGE_MEMBER | Edge::EDGE_CALL | Edge::EDGE_TYPE_OF));
|
TS_ASSERT(e.isType(Edge::EDGE_MEMBER | Edge::EDGE_CALL | Edge::EDGE_TYPE_OF));
|
||||||
@@ -188,9 +189,9 @@ public:
|
|||||||
|
|
||||||
void test_node_finds_child_node()
|
void test_node_finds_child_node()
|
||||||
{
|
{
|
||||||
Node a(Node::NODE_UNDEFINED, "A");
|
Node a(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
Node b(Node::NODE_UNDEFINED, "B");
|
Node b(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("B", "::")));
|
||||||
Node c(Node::NODE_UNDEFINED, "C");
|
Node c(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("C", "::")));
|
||||||
Edge e(Edge::EDGE_MEMBER, &a, &b);
|
Edge e(Edge::EDGE_MEMBER, &a, &b);
|
||||||
Edge e2(Edge::EDGE_MEMBER, &a, &c);
|
Edge e2(Edge::EDGE_MEMBER, &a, &c);
|
||||||
|
|
||||||
@@ -207,9 +208,9 @@ public:
|
|||||||
|
|
||||||
void test_node_can_not_find_child_node()
|
void test_node_can_not_find_child_node()
|
||||||
{
|
{
|
||||||
Node a(Node::NODE_UNDEFINED, "A");
|
Node a(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
Node b(Node::NODE_UNDEFINED, "B");
|
Node b(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("B", "::")));
|
||||||
Node c(Node::NODE_UNDEFINED, "C");
|
Node c(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("C", "::")));
|
||||||
Edge e(Edge::EDGE_MEMBER, &a, &b);
|
Edge e(Edge::EDGE_MEMBER, &a, &b);
|
||||||
Edge e2(Edge::EDGE_MEMBER, &a, &c);
|
Edge e2(Edge::EDGE_MEMBER, &a, &c);
|
||||||
|
|
||||||
@@ -225,9 +226,9 @@ public:
|
|||||||
|
|
||||||
void test_node_visits_child_nodes()
|
void test_node_visits_child_nodes()
|
||||||
{
|
{
|
||||||
Node a(Node::NODE_UNDEFINED, "A");
|
Node a(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
Node b(Node::NODE_UNDEFINED, "B");
|
Node b(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("B", "::")));
|
||||||
Node c(Node::NODE_UNDEFINED, "C");
|
Node c(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("C", "::")));
|
||||||
Edge e(Edge::EDGE_MEMBER, &a, &b);
|
Edge e(Edge::EDGE_MEMBER, &a, &b);
|
||||||
Edge e2(Edge::EDGE_MEMBER, &a, &c);
|
Edge e2(Edge::EDGE_MEMBER, &a, &c);
|
||||||
|
|
||||||
@@ -247,8 +248,8 @@ public:
|
|||||||
void test_graph_saves_nodes()
|
void test_graph_saves_nodes()
|
||||||
{
|
{
|
||||||
Graph graph;
|
Graph graph;
|
||||||
Node a(Node::NODE_UNDEFINED, "A");
|
Node a(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
Node b(Node::NODE_UNDEFINED, "B");
|
Node b(Node::NODE_UNDEFINED, std::make_shared<TokenComponentNameCached>(utility::splitToVector("B", "::")));
|
||||||
|
|
||||||
graph.addNode(&a);
|
graph.addNode(&a);
|
||||||
graph.addNode(&b);
|
graph.addNode(&b);
|
||||||
@@ -269,8 +270,8 @@ public:
|
|||||||
{
|
{
|
||||||
Graph graph;
|
Graph graph;
|
||||||
|
|
||||||
Node a(Node::NODE_FUNCTION, "A");
|
Node a(Node::NODE_FUNCTION, std::make_shared<TokenComponentNameCached>(utility::splitToVector("A", "::")));
|
||||||
Node b(Node::NODE_FUNCTION, "B");
|
Node b(Node::NODE_FUNCTION, std::make_shared<TokenComponentNameCached>(utility::splitToVector("B", "::")));
|
||||||
|
|
||||||
Edge e(Edge::EDGE_CALL, &a, &b);
|
Edge e(Edge::EDGE_CALL, &a, &b);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user