#ifndef TEST_STORAGE_H
#define TEST_STORAGE_H
#include <boost/filesystem.hpp>
#include "AccessKind.h"
#include "Edge.h"
#include "FilePath.h"
#include "LocationType.h"
#include "NameHierarchy.h"
#include "NodeType.h"
#include "Storage.h"
#include "utilityString.h"
class TestStorage
{
public:
static std::shared_ptr<TestStorage> create(std::shared_ptr<const Storage> storage)
{
std::shared_ptr<TestStorage> testStorage = std::make_shared<TestStorage>();
std::map<Id, FilePath> filePathMap;
for (const StorageFile& file: storage->getStorageFiles())
{
filePathMap.emplace(file.id, FilePath(file.filePath));
testStorage->files.emplace(file.filePath);
testStorage->addLine(
L"FILE: " + FilePath(file.filePath).fileName() +
(file.indexed ? L"" : L" non-indexed"));
}
std::map<Id, StorageComponentAccess> accessMap;
for (const StorageComponentAccess& access: storage->getComponentAccesses())
{
accessMap.emplace(access.nodeId, access);
}
std::multimap<Id, Id> occurrenceMap;
for (const StorageOccurrence& occurrence: storage->getStorageOccurrences())
{
occurrenceMap.emplace(occurrence.sourceLocationId, occurrence.elementId);
}
std::multimap<Id, StorageSourceLocation> tokenLocationMap;
std::multimap<Id, StorageSourceLocation> scopeLocationMap;
std::multimap<Id, StorageSourceLocation> signatureLocationMap;
std::multimap<Id, StorageSourceLocation> localSymbolLocationMap;
std::multimap<Id, StorageSourceLocation> qualifierLocationMap;
std::multimap<Id, StorageSourceLocation> errorLocationMap;
std::vector<StorageSourceLocation> commentLocations;
for (const StorageSourceLocation& location: storage->getStorageSourceLocations())
{
std::vector<Id> elementIds;
for (auto it = occurrenceMap.find(location.id);
it != occurrenceMap.end() && it->first == location.id;
it++)
{
elementIds.emplace_back(it->second);
}
if (elementIds.empty())
{
elementIds.emplace_back(0);
}
for (Id elementId: elementIds)
{
switch (intToLocationType(location.type))
{
case LOCATION_TOKEN:
if (elementId)
{
tokenLocationMap.emplace(elementId, location);
}
break;
case LOCATION_SCOPE:
if (elementId)
{
scopeLocationMap.emplace(elementId, location);
}
break;
case LOCATION_QUALIFIER:
if (elementId)
{
qualifierLocationMap.emplace(elementId, location);
}
break;
case LOCATION_LOCAL_SYMBOL:
if (elementId)
{
localSymbolLocationMap.emplace(elementId, location);
}
break;
case LOCATION_SIGNATURE:
if (elementId)
{
signatureLocationMap.emplace(elementId, location);
}
break;
case LOCATION_ERROR:
if (elementId)
{
errorLocationMap.emplace(elementId, location);
}
break;
case LOCATION_COMMENT:
commentLocations.emplace_back(location);
break;
default:
break;
}
}
}
std::map<Id, StorageNode> nodesMap;
std::set<Id> fileIdMap;
for (const StorageNode& node: storage->getStorageNodes())
{
nodesMap.emplace(node.id, node);
if (intToNodeKind(node.type) == NODE_FILE)
{
fileIdMap.insert(node.id);
}
std::wstring nameStr =
NameHierarchy::deserialize(node.serializedName).getQualifiedNameWithSignature();
for (auto qualifierLocationIt = qualifierLocationMap.find(node.id);
qualifierLocationIt != qualifierLocationMap.end() &&
qualifierLocationIt->first == node.id;
qualifierLocationIt++)
{
std::wstring locStr = addLocationStr(L"", qualifierLocationIt->second);
testStorage->qualifiers.emplace_back(nameStr + locStr);
testStorage->addLine(
L"QUALIFIER: " + nameStr +
addFileName(locStr, filePathMap[qualifierLocationIt->second.fileNodeId]));
}
std::vector<std::wstring>* bin = testStorage->getBinForNodeType(node.type);
if (bin != nullptr)
{
auto accessIt = accessMap.find(node.id);
if (accessIt != accessMap.end())
{
if (intToAccessKind(accessIt->second.type) != ACCESS_TEMPLATE_PARAMETER &&
intToAccessKind(accessIt->second.type) != ACCESS_TYPE_PARAMETER)
{
nameStr = accessKindToString(intToAccessKind(accessIt->second.type)) +
L' ' + nameStr;
}
}
bool added = false;
for (auto tokenLocationIt = tokenLocationMap.find(node.id);
tokenLocationIt != tokenLocationMap.end() && tokenLocationIt->first == node.id;
tokenLocationIt++)
{
added = false;
std::wstring locationStr = addLocationStr(L"", tokenLocationIt->second);
auto signatureLocationIt = signatureLocationMap.find(node.id);
if (signatureLocationIt != signatureLocationMap.end() &&
containsLocation(signatureLocationIt->second, tokenLocationIt->second))
{
locationStr = addLocationStr(locationStr, signatureLocationIt->second);
}
for (auto scopeLocationIt = scopeLocationMap.find(node.id);
scopeLocationIt != scopeLocationMap.end() &&
scopeLocationIt->first == node.id;
scopeLocationIt++)
{
if (containsLocation(scopeLocationIt->second, tokenLocationIt->second))
{
std::wstring locStr = addLocationStr(
locationStr, scopeLocationIt->second);
bin->emplace_back(nameStr + locStr);
testStorage->addLine(
nodeTypeToString(node.type) + L": " + nameStr +
addFileName(locStr, filePathMap[tokenLocationIt->second.fileNodeId]));
added = true;
}
}
if (!added)
{
bin->emplace_back(nameStr + locationStr);
testStorage->addLine(
nodeTypeToString(node.type) + L": " + nameStr +
addFileName(locationStr, filePathMap[tokenLocationIt->second.fileNodeId]));
added = true;
}
}
if (!added)
{
bin->emplace_back(nameStr);
testStorage->addLine(nodeTypeToString(node.type) + L": " + nameStr);
}
}
}
for (const StorageEdge& edge: storage->getStorageEdges())
{
auto targetIt = nodesMap.find(edge.targetNodeId);
if (targetIt == nodesMap.end())
{
continue;
}
auto sourceIt = nodesMap.find(edge.sourceNodeId);
if (sourceIt == nodesMap.end())
{
continue;
}
const StorageNode& target = targetIt->second;
const StorageNode& source = sourceIt->second;
std::vector<std::wstring>* bin = testStorage->getBinForEdgeType(edge.type);
if (bin != nullptr)
{
std::wstring sourceName =
NameHierarchy::deserialize(source.serializedName).getQualifiedNameWithSignature();
if (fileIdMap.find(edge.sourceNodeId) != fileIdMap.end() &&
FilePath(sourceName).exists())
{
sourceName = FilePath(sourceName).fileName();
}
std::wstring targetName =
NameHierarchy::deserialize(target.serializedName).getQualifiedNameWithSignature();
if (fileIdMap.find(edge.targetNodeId) != fileIdMap.end() &&
FilePath(targetName).exists())
{
targetName = FilePath(targetName).fileName();
}
std::wstring nameStr = sourceName + L" -> " + targetName;
bool added = false;
for (auto tokenLocationIt = tokenLocationMap.find(edge.id);
tokenLocationIt != tokenLocationMap.end() && tokenLocationIt->first == edge.id;
tokenLocationIt++)
{
std::wstring locStr = addLocationStr(L"", tokenLocationIt->second);
bin->emplace_back(nameStr + locStr);
testStorage->addLine(
edgeTypeToString(edge.type) + L": " + nameStr +
addFileName(locStr, filePathMap[tokenLocationIt->second.fileNodeId]));
added = true;
}
if (!added)
{
bin->emplace_back(nameStr);
testStorage->addLine(edgeTypeToString(edge.type) + L": " + nameStr);
}
}
}
for (const StorageLocalSymbol& localSymbol: storage->getStorageLocalSymbols())
{
bool added = false;
for (auto localSymbolLocationIt = localSymbolLocationMap.find(localSymbol.id);
localSymbolLocationIt != localSymbolLocationMap.end() &&
localSymbolLocationIt->first == localSymbol.id;
localSymbolLocationIt++)
{
std::wstring locStr = addLocationStr(L"", localSymbolLocationIt->second);
testStorage->localSymbols.emplace_back(localSymbol.name + locStr);
testStorage->addLine(
L"LOCAL_SYMBOL: " + localSymbol.name +
addFileName(locStr, filePathMap[localSymbolLocationIt->second.fileNodeId]));
added = true;
}
if (!added)
{
testStorage->localSymbols.emplace_back(localSymbol.name);
testStorage->addLine(L"LOCAL_SYMBOL: " + localSymbol.name);
}
}
for (const StorageSourceLocation& location: commentLocations)
{
std::wstring locStr = addLocationStr(L"", location);
testStorage->comments.emplace_back(L"comment" + locStr);
testStorage->addLine(
L"COMMENT: comment" + addFileName(locStr, filePathMap[location.fileNodeId]));
}
for (const StorageError& error: storage->getErrors())
{
for (auto errorLocationIt = errorLocationMap.find(error.id);
errorLocationIt != errorLocationMap.end() && errorLocationIt->first == error.id;
errorLocationIt++)
{
std::wstring locStr = addLocationStr(L"", errorLocationIt->second);
testStorage->errors.emplace_back(error.message + locStr);
testStorage->addLine(
L"ERROR: " + error.message +
addFileName(locStr, filePathMap[errorLocationIt->second.fileNodeId]));
}
}
return testStorage;
}
std::vector<std::wstring> errors;
std::vector<std::wstring> qualifiers;
std::vector<std::wstring> packages;
std::vector<std::wstring> typedefs;
std::vector<std::wstring> builtinTypes;
std::vector<std::wstring> classes;
std::vector<std::wstring> unions;
std::vector<std::wstring> interfaces;
std::vector<std::wstring> annotations;
std::vector<std::wstring> enums;
std::vector<std::wstring> enumConstants;
std::vector<std::wstring> functions;
std::vector<std::wstring> fields;
std::vector<std::wstring> globalVariables;
std::vector<std::wstring> methods;
std::vector<std::wstring> namespaces;
std::vector<std::wstring> modules;
std::vector<std::wstring> structs;
std::vector<std::wstring> macros;
std::vector<std::wstring> typeParameters;
std::vector<std::wstring> localSymbols;
std::set<std::wstring> files;
std::vector<std::wstring> comments;
std::vector<std::wstring> inheritances;
std::vector<std::wstring> overrides;
std::vector<std::wstring> calls;
std::vector<std::wstring> usages;
std::vector<std::wstring> typeUses;
std::vector<std::wstring> macroUses;
std::vector<std::wstring> annotationUses;
std::vector<std::wstring> typeArguments;
std::vector<std::wstring> templateSpecializations;
std::vector<std::wstring> includes;
std::vector<std::wstring> imports;
std::vector<std::string> m_lines;
private:
static std::wstring nodeTypeToString(int nodeType)
{
switch (intToNodeKind(nodeType))
{
case NODE_BUILTIN_TYPE:
return L"SYMBOL_BUILTIN_TYPE";
case NODE_CLASS:
return L"SYMBOL_CLASS";
case NODE_ENUM:
return L"SYMBOL_ENUM";
case NODE_ENUM_CONSTANT:
return L"SYMBOL_ENUM_CONSTANT";
case NODE_FIELD:
return L"SYMBOL_FIELD";
case NODE_FUNCTION:
return L"SYMBOL_FUNCTION";
case NODE_GLOBAL_VARIABLE:
return L"SYMBOL_GLOBAL_VARIABLE";
case NODE_INTERFACE:
return L"SYMBOL_INTERFACE";
case NODE_MACRO:
return L"SYMBOL_MACRO";
case NODE_METHOD:
return L"SYMBOL_METHOD";
case NODE_MODULE:
return L"SYMBOL_MODULE";
case NODE_NAMESPACE:
return L"SYMBOL_NAMESPACE";
case NODE_PACKAGE:
return L"SYMBOL_PACKAGE";
case NODE_STRUCT:
return L"SYMBOL_STRUCT";
case NODE_TYPEDEF:
return L"SYMBOL_TYPEDEF";
case NODE_TYPE_PARAMETER:
return L"SYMBOL_TYPE_PARAMETER";
case NODE_UNION:
return L"SYMBOL_UNION";
default:
break;
}
return L"SYMBOL_NON_INDEXED";
}
static std::wstring edgeTypeToString(int edgeType)
{
switch (Edge::intToType(edgeType))
{
case Edge::EDGE_TYPE_USAGE:
return L"REFERENCE_TYPE_USAGE";
case Edge::EDGE_USAGE:
return L"REFERENCE_USAGE";
case Edge::EDGE_CALL:
return L"REFERENCE_CALL";
case Edge::EDGE_INHERITANCE:
return L"REFERENCE_INHERITANCE";
case Edge::EDGE_OVERRIDE:
return L"REFERENCE_OVERRIDE";
case Edge::EDGE_TYPE_ARGUMENT:
return L"REFERENCE_TYPE_ARGUMENT";
case Edge::EDGE_TEMPLATE_SPECIALIZATION:
return L"REFERENCE_TEMPLATE_SPECIALIZATION";
case Edge::EDGE_INCLUDE:
return L"REFERENCE_INCLUDE";
case Edge::EDGE_IMPORT:
return L"REFERENCE_IMPORT";
case Edge::EDGE_MACRO_USAGE:
return L"REFERENCE_MACRO_USAGE";
case Edge::EDGE_ANNOTATION_USAGE:
return L"REFERENCE_ANNOTATION_USAGE";
default:
break;
}
return L"REFERENCE_UNDEFINED";
}
std::vector<std::wstring>* getBinForNodeType(int nodeType)
{
switch (intToNodeKind(nodeType))
{
case NODE_PACKAGE:
return &packages;
case NODE_TYPEDEF:
return &typedefs;
case NODE_BUILTIN_TYPE:
return &builtinTypes;
case NODE_CLASS:
return &classes;
case NODE_UNION:
return &unions;
case NODE_INTERFACE:
return &interfaces;
case NODE_ANNOTATION:
return &annotations;
case NODE_ENUM:
return &enums;
case NODE_ENUM_CONSTANT:
return &enumConstants;
case NODE_FUNCTION:
return &functions;
case NODE_FIELD:
return &fields;
case NODE_GLOBAL_VARIABLE:
return &globalVariables;
case NODE_METHOD:
return &methods;
case NODE_MODULE:
return &modules;
case NODE_NAMESPACE:
return &namespaces;
case NODE_STRUCT:
return &structs;
case NODE_MACRO:
return ¯os;
case NODE_TYPE_PARAMETER:
return &typeParameters;
default:
break;
}
return nullptr;
}
std::vector<std::wstring>* getBinForEdgeType(int edgeType)
{
switch (Edge::intToType(edgeType))
{
case Edge::EDGE_TYPE_USAGE:
return &typeUses;
case Edge::EDGE_USAGE:
return &usages;
case Edge::EDGE_CALL:
return &calls;
case Edge::EDGE_INHERITANCE:
return &inheritances;
case Edge::EDGE_OVERRIDE:
return &overrides;
case Edge::EDGE_TYPE_ARGUMENT:
return &typeArguments;
case Edge::EDGE_TEMPLATE_SPECIALIZATION:
return &templateSpecializations;
case Edge::EDGE_INCLUDE:
return &includes;
case Edge::EDGE_IMPORT:
return &imports;
case Edge::EDGE_MACRO_USAGE:
return ¯oUses;
case Edge::EDGE_ANNOTATION_USAGE:
return &annotationUses;
default:
break;
}
return nullptr;
}
static std::wstring addLocationStr(const std::wstring& locationStr, const StorageSourceLocation& loc)
{
return L" <" + std::to_wstring(loc.startLine) + L':' + std::to_wstring(loc.startCol) +
locationStr + L' ' + std::to_wstring(loc.endLine) + L':' + std::to_wstring(loc.endCol) +
L'>';
}
static std::wstring addFileName(const std::wstring& locationStr, const FilePath& filePath)
{
return L" [" + filePath.fileName() + locationStr + L']';
}
static bool containsLocation(const StorageSourceLocation& out, const StorageSourceLocation& in)
{
if (out.startLine > in.startLine)
{
return false;
}
if (out.startLine == in.startLine && out.startCol > in.startCol)
{
return false;
}
if (out.endLine < in.endLine)
{
return false;
}
if (out.endLine == in.endLine && out.endCol < in.endCol)
{
return false;
}
return true;
}
void addLine(const std::wstring& message)
{
m_lines.emplace_back(utility::encodeToUtf8(message) + '\n');
}
};
#endif