#include "ParserClientImpl.h"
#include "Edge.h"
#include "Node.h"
#include "ParseLocation.h"
ParserClientImpl::ParserClientImpl(IntermediateStorage* const storage): m_storage(storage) {}
Id ParserClientImpl::recordFile(const FilePath& filePath, bool indexed)
{
Id fileId = addFileName(filePath);
m_storage->addFile(StorageFile(fileId, filePath.wstr(), L"", "", indexed, true));
return fileId;
}
void ParserClientImpl::recordFileLanguage(Id fileId, const std::wstring& languageIdentifier)
{
m_storage->setFileLanguage(fileId, languageIdentifier);
}
Id ParserClientImpl::recordSymbol(const NameHierarchy& symbolName)
{
return addNodeHierarchy(symbolName);
}
void ParserClientImpl::recordSymbolKind(Id symbolId, SymbolKind symbolKind)
{
m_storage->setNodeType(symbolId, nodeKindToInt(symbolKindToNodeKind(symbolKind)));
}
void ParserClientImpl::recordAccessKind(Id symbolId, AccessKind accessKind)
{
if (accessKind != ACCESS_NONE)
{
m_storage->addComponentAccess(StorageComponentAccess(symbolId, accessKindToInt(accessKind)));
}
}
void ParserClientImpl::recordDefinitionKind(Id symbolId, DefinitionKind definitionKind)
{
if (definitionKind != DEFINITION_NONE)
{
m_storage->addSymbol(StorageSymbol(symbolId, definitionKindToInt(definitionKind)));
}
}
Id ParserClientImpl::recordReference(
ReferenceKind referenceKind, Id referencedSymbolId, Id contextSymbolId, const ParseLocation& location)
{
Id edgeId = addEdge(referenceKindToEdgeType(referenceKind), contextSymbolId, referencedSymbolId);
if (edgeId)
{
addSourceLocation(edgeId, location, LOCATION_TOKEN);
}
return edgeId;
}
void ParserClientImpl::recordLocalSymbol(const std::wstring& name, const ParseLocation& location)
{
const Id localSymbolId = m_storage->addLocalSymbol(name);
addSourceLocation(localSymbolId, location, LOCATION_LOCAL_SYMBOL);
}
void ParserClientImpl::recordLocation(Id elementId, const ParseLocation& location, ParseLocationType type)
{
addSourceLocation(elementId, location, parseLocationTypeToLocationType(type));
}
void ParserClientImpl::recordComment(const ParseLocation& location)
{
if (!location.isValid())
{
return;
}
m_storage->addSourceLocation(StorageSourceLocationData(
location.fileId,
location.startLineNumber,
location.startColumnNumber,
location.endLineNumber,
location.endColumnNumber,
locationTypeToInt(LOCATION_COMMENT)));
}
void ParserClientImpl::recordError(
const std::wstring& message,
bool fatal,
bool indexed,
const FilePath& translationUnit,
const ParseLocation& location)
{
if (location.fileId != 0)
{
Id errorId = m_storage->addError(
StorageErrorData(message, translationUnit.wstr(), fatal, indexed));
addSourceLocation(errorId, location, LOCATION_ERROR);
}
}
bool ParserClientImpl::hasContent() const
{
return m_storage->getByteSize(1) > 0;
}
NodeKind ParserClientImpl::symbolKindToNodeKind(SymbolKind symbolKind) const
{
switch (symbolKind)
{
case SYMBOL_ANNOTATION:
return NODE_ANNOTATION;
case SYMBOL_BUILTIN_TYPE:
return NODE_BUILTIN_TYPE;
case SYMBOL_CLASS:
return NODE_CLASS;
case SYMBOL_ENUM:
return NODE_ENUM;
case SYMBOL_ENUM_CONSTANT:
return NODE_ENUM_CONSTANT;
case SYMBOL_FIELD:
return NODE_FIELD;
case SYMBOL_FUNCTION:
return NODE_FUNCTION;
case SYMBOL_GLOBAL_VARIABLE:
return NODE_GLOBAL_VARIABLE;
case SYMBOL_INTERFACE:
return NODE_INTERFACE;
case SYMBOL_MACRO:
return NODE_MACRO;
case SYMBOL_METHOD:
return NODE_METHOD;
case SYMBOL_MODULE:
return NODE_MODULE;
case SYMBOL_NAMESPACE:
return NODE_NAMESPACE;
case SYMBOL_PACKAGE:
return NODE_PACKAGE;
case SYMBOL_STRUCT:
return NODE_STRUCT;
case SYMBOL_TYPEDEF:
return NODE_TYPEDEF;
case SYMBOL_TYPE_PARAMETER:
return NODE_TYPE_PARAMETER;
case SYMBOL_UNION:
return NODE_UNION;
default:
break;
}
return NODE_SYMBOL;
}
Edge::EdgeType ParserClientImpl::referenceKindToEdgeType(ReferenceKind referenceKind) const
{
switch (referenceKind)
{
case REFERENCE_TYPE_USAGE:
return Edge::EDGE_TYPE_USAGE;
case REFERENCE_USAGE:
return Edge::EDGE_USAGE;
case REFERENCE_CALL:
return Edge::EDGE_CALL;
case REFERENCE_INHERITANCE:
return Edge::EDGE_INHERITANCE;
case REFERENCE_OVERRIDE:
return Edge::EDGE_OVERRIDE;
case REFERENCE_TYPE_ARGUMENT:
return Edge::EDGE_TYPE_ARGUMENT;
case REFERENCE_TEMPLATE_SPECIALIZATION:
return Edge::EDGE_TEMPLATE_SPECIALIZATION;
case REFERENCE_INCLUDE:
return Edge::EDGE_INCLUDE;
case REFERENCE_IMPORT:
return Edge::EDGE_IMPORT;
case REFERENCE_MACRO_USAGE:
return Edge::EDGE_MACRO_USAGE;
case REFERENCE_ANNOTATION_USAGE:
return Edge::EDGE_ANNOTATION_USAGE;
default:
break;
}
return Edge::EDGE_UNDEFINED;
}
LocationType ParserClientImpl::parseLocationTypeToLocationType(ParseLocationType type) const
{
switch (type)
{
case ParseLocationType::TOKEN:
return LOCATION_TOKEN;
case ParseLocationType::SCOPE:
return LOCATION_SCOPE;
case ParseLocationType::SIGNATURE:
return LOCATION_SIGNATURE;
case ParseLocationType::QUALIFIER:
return LOCATION_QUALIFIER;
case ParseLocationType::LOCAL:
return LOCATION_LOCAL_SYMBOL;
}
return LOCATION_TOKEN;
}
Id ParserClientImpl::addNodeHierarchy(const NameHierarchy& nameHierarchy)
{
Id childNodeId = 0;
Id firstNodeId = 0;
for (size_t i = nameHierarchy.size(); i > 0; i--)
{
std::pair<Id, bool> ret = m_storage->addNode(StorageNodeData(
nodeKindToInt(NODE_SYMBOL), NameHierarchy::serializeRange(nameHierarchy, 0, i)));
if (!firstNodeId)
{
firstNodeId = ret.first;
}
if (childNodeId != 0)
{
addEdge(Edge::EDGE_MEMBER, ret.first, childNodeId);
}
if (!ret.second)
{
return firstNodeId;
}
childNodeId = ret.first;
}
return firstNodeId;
}
Id ParserClientImpl::addFileName(const FilePath& filePath)
{
const std::wstring file = filePath.wstr();
auto it = m_fileIdMap.find(file);
if (it != m_fileIdMap.end())
{
return it->second;
}
const Id fileId = addNodeHierarchy(NameHierarchy(file, NAME_DELIMITER_FILE));
m_storage->setNodeType(fileId, nodeKindToInt(NODE_FILE));
m_fileIdMap.emplace(file, fileId);
return fileId;
}
Id ParserClientImpl::addEdge(int type, Id sourceId, Id targetId)
{
if (sourceId && targetId)
{
return m_storage->addEdge(StorageEdgeData(type, sourceId, targetId));
}
return 0;
}
void ParserClientImpl::addSourceLocation(Id elementId, const ParseLocation& location, LocationType type)
{
if (!location.isValid())
{
return;
}
Id sourceLocationId = m_storage->addSourceLocation(StorageSourceLocationData(
location.fileId,
location.startLineNumber,
location.startColumnNumber,
location.endLineNumber,
location.endColumnNumber,
locationTypeToInt(type)));
m_storage->addOccurrence(StorageOccurrence(elementId, sourceLocationId));
}