data: Saving TokenLocations in Storage

This change adds structures for saving TokenLocations in the Storage and improves the location derival in the
ASTVisitor:
* TokenLocation saves an Id of a Token. For each Token two TokenLocations are created for both start- and endpoint. They
  keep a reference to each other and know whether they are start or end.
* TokenLocationLine saves all TokenLocations in a line and the lineNumber.
* TokenLocationFile saves all TokenLocationLines of a specific file and the filePath.
* TokenLocationCollection saves multiple TokenLocationFiles.
* TokenLocation can derive it's lineNumber and filePath through references to first TokenLocationLine and from there to
  TokenLocationFile.
This commit is contained in:
Eberhard Graether
2014-07-01 10:49:12 +02:00
parent e3cf57e2ec
commit cf6d17584f
27 changed files with 1109 additions and 243 deletions
+152
View File
@@ -0,0 +1,152 @@
#include "data/location/TokenLocationFile.h"
#include "data/location/TokenLocation.h"
#include "data/location/TokenLocationLine.h"
#include "utility/logging/logging.h"
TokenLocationFile::TokenLocationFile(const std::string& filePath)
: m_filePath(filePath)
{
}
TokenLocationFile::~TokenLocationFile()
{
}
const TokenLocationFile::TokenLocationLineMapType& TokenLocationFile::getTokenLocationLines() const
{
return m_lines;
}
size_t TokenLocationFile::getTokenLocationLineCount() const
{
return m_lines.size();
}
const std::string& TokenLocationFile::getFilePath() const
{
return m_filePath;
}
TokenLocation* TokenLocationFile::addTokenLocation(
Id tokenId,
unsigned int startLineNumber, unsigned int startColumnNumber,
unsigned int endLineNumber, unsigned int endColumnNumber)
{
TokenLocationLine* line = createTokenLocationLine(startLineNumber);
TokenLocation* start = line->addStartTokenLocation(tokenId, startColumnNumber);
if (startLineNumber != endLineNumber)
{
line = createTokenLocationLine(endLineNumber);
}
line->addEndTokenLocation(start, endColumnNumber);
return start;
}
void TokenLocationFile::removeTokenLocation(TokenLocation* location)
{
TokenLocationLine* line = location->getTokenLocationLine();
TokenLocation* otherLocation = location->getOtherTokenLocation();
TokenLocationLine* otherLine = otherLocation->getTokenLocationLine();
line->removeTokenLocation(location);
if (!line->getTokenLocationCount())
{
m_lines.erase(line->getLineNumber());
}
otherLine->removeTokenLocation(otherLocation);
if (!otherLine->getTokenLocationCount())
{
m_lines.erase(otherLine->getLineNumber());
}
}
void TokenLocationFile::forEachTokenLocationLine(std::function<void(TokenLocationLine*)> func) const
{
for (const TokenLocationLinePairType& line : m_lines)
{
func(line.second.get());
}
}
TokenLocation* TokenLocationFile::addTokenLocationAsPlainCopy(const TokenLocation* location)
{
unsigned int lineNumber = location->getTokenLocationLine()->getLineNumber();
TokenLocationLine* line = createTokenLocationLine(lineNumber);
// Check whether this location was already added or if the other TokenLocation was added.
TokenLocation* otherLocation = line->getTokenLocationById(location->getId());
if (otherLocation)
{
if (otherLocation->isStartTokenLocation() == location->isStartTokenLocation())
{
// The location was already added.
return otherLocation;
}
}
else
{
// Look for the other location in it's line.
unsigned int otherLineNumber = location->getOtherTokenLocation()->getTokenLocationLine()->getLineNumber();
if (lineNumber != otherLineNumber)
{
TokenLocationLine* otherLine = findTokenLocationLine(otherLineNumber);
if (otherLine)
{
otherLocation = otherLine->getTokenLocationById(location->getId());
}
}
}
TokenLocation* copy = line->addTokenLocationAsPlainCopy(location);
// If the other location was added before, then link them with each other.
if (otherLocation)
{
otherLocation->setOtherTokenLocation(copy);
copy->setOtherTokenLocation(otherLocation);
}
return copy;
}
TokenLocationLine* TokenLocationFile::findTokenLocationLine(unsigned int lineNumber) const
{
TokenLocationLineMapType::const_iterator it = m_lines.find(lineNumber);
if (it != m_lines.end())
{
return it->second.get();
}
return nullptr;
}
TokenLocationLine* TokenLocationFile::createTokenLocationLine(unsigned int lineNumber)
{
TokenLocationLine* line = findTokenLocationLine(lineNumber);
if (line)
{
return line;
}
std::shared_ptr<TokenLocationLine> linePtr = std::make_shared<TokenLocationLine>(this, lineNumber);
m_lines.emplace(lineNumber, linePtr);
return linePtr.get();
}
std::ostream& operator<<(std::ostream& ostream, const TokenLocationFile& file)
{
ostream << "file \"" << file.getFilePath() << "\"\n";
file.forEachTokenLocationLine([&ostream](TokenLocationLine* l)
{
ostream << *l << '\n';
});
return ostream;
}