Files
Sourcetrail/src/lib/data/parser/ParserClientImpl.cpp
T

345 lines
8.2 KiB
C++

#include "data/parser/ParserClientImpl.h"
#include "data/parser/ParseLocation.h"
#include "data/graph/Node.h"
#include "data/graph/Edge.h"
#include "utility/logging/logging.h"
#include "utility/utility.h"
#include "data/location/TokenLocation.h"
ParserClientImpl::ParserClientImpl()
{
}
ParserClientImpl::~ParserClientImpl()
{
}
void ParserClientImpl::setStorage(std::shared_ptr<IntermediateStorage> storage)
{
m_storage = storage;
}
void ParserClientImpl::resetStorage()
{
m_storage.reset();
}
void ParserClientImpl::startParsingFile()
{
}
void ParserClientImpl::finishParsingFile()
{
}
Id ParserClientImpl::recordSymbol(
const NameHierarchy& symbolName, SymbolKind symbolType,
AccessKind access, DefinitionType definitionType
)
{
Id nodeId = addNodeHierarchy(symbolKindToNodeType(symbolType), symbolName, definitionType);
addAccess(nodeId, access);
return nodeId;
}
Id ParserClientImpl::recordSymbol(
const NameHierarchy& symbolName, SymbolKind symbolType,
const ParseLocation& location,
AccessKind access, DefinitionType definitionType
)
{
Id nodeId = recordSymbol(symbolName, symbolType, access, definitionType);
addSourceLocation(nodeId, location, locationTypeToInt(LOCATION_TOKEN));
return nodeId;
}
Id ParserClientImpl::recordSymbol(
const NameHierarchy& symbolName, SymbolKind symbolType,
const ParseLocation& location, const ParseLocation& scopeLocation,
AccessKind access, DefinitionType definitionType
)
{
Id nodeId = recordSymbol(symbolName, symbolType, location, access, definitionType);
addSourceLocation(nodeId, scopeLocation, locationTypeToInt(LOCATION_SCOPE));
return nodeId;
}
void ParserClientImpl::recordReference(
ReferenceKind referenceKind, const NameHierarchy& referencedName, const NameHierarchy& contextName,
const ParseLocation& location)
{
Id contextNodeId = addNodeHierarchy(Node::NODE_UNDEFINED, contextName, DEFINITION_NONE);
Id referencedNodeId = addNodeHierarchy(Node::NODE_UNDEFINED, referencedName, DEFINITION_NONE);
Id edgeId = addEdge(referenceKindToEdgeType(referenceKind), contextNodeId, referencedNodeId);
addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN));
}
void ParserClientImpl::onError(const ParseLocation& location, const std::string& message, bool fatal, bool indexed)
{
if (location.isValid())
{
addError(message, fatal, indexed, location);
}
}
void ParserClientImpl::onLocalSymbolParsed(const std::string& name, const ParseLocation& location)
{
Id localSymbolId = addLocalSymbol(name);
addSourceLocation(localSymbolId, location, locationTypeToInt(LOCATION_LOCAL_SYMBOL));
}
void ParserClientImpl::onFileParsed(const FileInfo& fileInfo)
{
addFile(fileInfo.path.fileName(), fileInfo.path.str(), fileInfo.lastWriteTime.toString());
}
void ParserClientImpl::onCommentParsed(const ParseLocation& location)
{
addFile(location.filePath.str());
addCommentLocation(location);
}
Node::NodeType ParserClientImpl::symbolKindToNodeType(SymbolKind symbolType) const
{
switch (symbolType)
{
case SYMBOL_BUILTIN_TYPE:
return Node::NODE_BUILTIN_TYPE;
case SYMBOL_CLASS:
return Node::NODE_CLASS;
case SYMBOL_ENUM:
return Node::NODE_ENUM;
case SYMBOL_ENUM_CONSTANT:
return Node::NODE_ENUM_CONSTANT;
case SYMBOL_FIELD:
return Node::NODE_FIELD;
case SYMBOL_FUNCTION:
return Node::NODE_FUNCTION;
case SYMBOL_GLOBAL_VARIABLE:
return Node::NODE_GLOBAL_VARIABLE;
case SYMBOL_INTERFACE:
return Node::NODE_INTERFACE;
case SYMBOL_MACRO:
return Node::NODE_MACRO;
case SYMBOL_METHOD:
return Node::NODE_METHOD;
case SYMBOL_NAMESPACE:
return Node::NODE_NAMESPACE;
case SYMBOL_PACKAGE:
return Node::NODE_PACKAGE;
case SYMBOL_STRUCT:
return Node::NODE_STRUCT;
case SYMBOL_TEMPLATE_PARAMETER:
return Node::NODE_TEMPLATE_PARAMETER_TYPE;
case SYMBOL_TYPEDEF:
return Node::NODE_TYPEDEF;
case SYMBOL_TYPE_PARAMETER:
return Node::NODE_TYPE_PARAMETER;
case SYMBOL_UNION:
return Node::NODE_TYPE;
default:
break;
}
return Node::NODE_UNDEFINED;
}
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_TEMPLATE_ARGUMENT:
return Edge::EDGE_TEMPLATE_ARGUMENT;
case REFERENCE_TYPE_ARGUMENT:
return Edge::EDGE_TYPE_ARGUMENT;
case REFERENCE_TEMPLATE_DEFAULT_ARGUMENT:
return Edge::EDGE_TEMPLATE_DEFAULT_ARGUMENT;
case REFERENCE_TEMPLATE_SPECIALIZATION:
return Edge::EDGE_TEMPLATE_SPECIALIZATION;
case REFERENCE_TEMPLATE_MEMBER_SPECIALIZATION:
return Edge::EDGE_TEMPLATE_MEMBER_SPECIALIZATION;
case REFERENCE_INCLUDE:
return Edge::EDGE_INCLUDE;
case REFERENCE_IMPORT:
return Edge::EDGE_IMPORT;
case REFERENCE_MACRO_USAGE:
return Edge::EDGE_MACRO_USAGE;
default:
break;
}
return Edge::EDGE_UNDEFINED;
}
void ParserClientImpl::addAccess(Id nodeId, AccessKind access)
{
if (access != ACCESS_NONE)
{
addComponentAccess(nodeId, accessKindToInt(access));
}
}
Id ParserClientImpl::addNodeHierarchy(Node::NodeType nodeType, NameHierarchy nameHierarchy, DefinitionType definitionType)
{
if (nameHierarchy.size() == 0)
{
return 0;
}
Id parentNodeId = 0;
NameHierarchy currentNameHierarchy;
for (size_t i = 0; i < nameHierarchy.size(); i++)
{
currentNameHierarchy.push(nameHierarchy[i]);
const bool currentIsLastElement = (i == nameHierarchy.size() - 1);
Node::NodeType currentType = (currentIsLastElement ? nodeType : Node::NODE_UNDEFINED); // TODO: rename to unknown!
DefinitionType currentDefinitionType = (currentIsLastElement ? definitionType : DEFINITION_NONE);
Id nodeId = addNode(currentType, currentNameHierarchy, currentDefinitionType);
// Todo: performance optimization: check if node exists. dont add edge if it existed before...
if (parentNodeId != 0)
{
addEdge(Edge::EDGE_MEMBER, parentNodeId, nodeId);
}
parentNodeId = nodeId;
}
return parentNodeId;
}
Id ParserClientImpl::addFile(const std::string& name, const std::string& filePath, const std::string& modificationTime)
{
if (!m_storage)
{
return 0;
}
return m_storage->addFile(name, filePath, modificationTime);
}
Id ParserClientImpl::addFile(const std::string& filePath)
{
if (!m_storage)
{
return 0;
}
return m_storage->addFile("", filePath, "");
}
Id ParserClientImpl::addNode(Node::NodeType nodeType, NameHierarchy nameHierarchy, DefinitionType definitionType)
{
if (!m_storage)
{
return 0;
}
return m_storage->addNode(Node::typeToInt(nodeType), NameHierarchy::serialize(nameHierarchy), definitionTypeToInt(definitionType));
}
Id ParserClientImpl::addEdge(int type, Id sourceId, Id targetId)
{
if (!m_storage)
{
return 0;
}
if (!sourceId || !targetId)
{
return 0;
}
return m_storage->addEdge(type, sourceId, targetId);
}
Id ParserClientImpl::addLocalSymbol(const std::string& name)
{
if (!m_storage)
{
return 0;
}
return m_storage->addLocalSymbol(name);
}
void ParserClientImpl::addSourceLocation(Id elementId, const ParseLocation& location, int type)
{
if (!m_storage)
{
return;
}
if (!location.isValid())
{
return;
}
if (location.filePath.empty())
{
LOG_ERROR("no filename set!");
return;
}
Id sourceLocationId = m_storage->addSourceLocation(
addFile(location.filePath.str()),
location.startLineNumber,
location.startColumnNumber,
location.endLineNumber,
location.endColumnNumber,
type
);
m_storage->addOccurrence(
elementId,
sourceLocationId
);
}
void ParserClientImpl::addComponentAccess(Id nodeId , int type)
{
if (!m_storage)
{
return;
}
m_storage->addComponentAccess(nodeId, type);
}
void ParserClientImpl::addCommentLocation(const ParseLocation& location)
{
if (!m_storage)
{
return;
}
m_storage->addCommentLocation(
addFile(location.filePath.str()),
location.startLineNumber,
location.startColumnNumber,
location.endLineNumber,
location.endColumnNumber
);
}
void ParserClientImpl::addError(const std::string& message, bool fatal, bool indexed, const ParseLocation& location)
{
if (!m_storage)
{
return;
}
m_storage->addError(message, location.filePath, location.startLineNumber, location.startColumnNumber, fatal, indexed);
}