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
+126
View File
@@ -0,0 +1,126 @@
#include "data/location/TokenLocation.h"
#include "data/location/TokenLocationLine.h"
TokenLocation::TokenLocation(Id tokenId, TokenLocationLine* line, unsigned int columnNumber, bool isStart)
: TokenLocation(s_locationId++, tokenId, line, columnNumber, isStart)
{
}
TokenLocation::TokenLocation(Id id, Id tokenId, TokenLocationLine* line, unsigned int columnNumber, bool isStart)
: m_id(id)
, m_tokenId(tokenId)
, m_line(line)
, m_columnNumber(columnNumber)
, m_other(nullptr)
, m_isStart(isStart)
{
}
TokenLocation::~TokenLocation()
{
}
Id TokenLocation::getId() const
{
return m_id;
}
Id TokenLocation::getTokenId() const
{
return m_tokenId;
}
TokenLocationLine* TokenLocation::getTokenLocationLine() const
{
return m_line;
}
TokenLocationFile* TokenLocation::getTokenLocationFile() const
{
return m_line->getTokenLocationFile();
}
unsigned int TokenLocation::getColumnNumber() const
{
return m_columnNumber;
}
unsigned int TokenLocation::getLineNumber() const
{
return m_line->getLineNumber();
}
const std::string& TokenLocation::getFilePath() const
{
return m_line->getFilePath();
}
TokenLocation* TokenLocation::getOtherTokenLocation() const
{
return m_other;
}
void TokenLocation::setOtherTokenLocation(TokenLocation* location)
{
m_other = location;
}
TokenLocation* TokenLocation::getStartTokenLocation()
{
if (m_isStart)
{
return this;
}
else
{
return m_other;
}
}
TokenLocation* TokenLocation::getEndTokenLocation()
{
if (!m_isStart)
{
return this;
}
else
{
return m_other;
}
}
bool TokenLocation::isStartTokenLocation() const
{
return m_isStart;
}
bool TokenLocation::isEndTokenLocation() const
{
return !m_isStart;
}
std::shared_ptr<TokenLocation> TokenLocation::createPlainCopy(TokenLocationLine* line) const
{
return std::shared_ptr<TokenLocation>(new TokenLocation(m_id, m_tokenId, line, m_columnNumber, m_isStart));
}
Id TokenLocation::s_locationId = 1;
std::ostream& operator<<(std::ostream& ostream, const TokenLocation& location)
{
if ((&location)->isStartTokenLocation())
{
ostream << "<";
}
ostream << location.getColumnNumber() << ":[" << location.getTokenId() << "]";
if ((&location)->isEndTokenLocation())
{
ostream << ">";
}
ostream << " ";
return ostream;
}
+57
View File
@@ -0,0 +1,57 @@
#ifndef TOKEN_LOCATION_H
#define TOKEN_LOCATION_H
#include <memory>
#include <ostream>
#include <string>
#include "utility/types.h"
class Token;
class TokenLocationFile;
class TokenLocationLine;
class TokenLocation
{
public:
TokenLocation(Id tokenId, TokenLocationLine* line, unsigned int columnNumber, bool isStart);
TokenLocation(Id id, Id tokenId, TokenLocationLine* line, unsigned int columnNumber, bool isStart);
~TokenLocation();
Id getId() const;
Id getTokenId() const;
TokenLocationLine* getTokenLocationLine() const;
TokenLocationFile* getTokenLocationFile() const;
unsigned int getColumnNumber() const;
unsigned int getLineNumber() const;
const std::string& getFilePath() const;
TokenLocation* getOtherTokenLocation() const;
void setOtherTokenLocation(TokenLocation* location);
TokenLocation* getStartTokenLocation();
TokenLocation* getEndTokenLocation();
bool isStartTokenLocation() const;
bool isEndTokenLocation() const;
std::shared_ptr<TokenLocation> createPlainCopy(TokenLocationLine* line) const;
private:
static Id s_locationId;
const Id m_id;
const Id m_tokenId;
TokenLocationLine* const m_line;
const unsigned int m_columnNumber;
TokenLocation* m_other;
const bool m_isStart;
};
std::ostream& operator<<(std::ostream& ostream, const TokenLocation& location);
#endif // TOKEN_LOCATION_H
@@ -0,0 +1,138 @@
#include "data/location/TokenLocationCollection.h"
#include "data/location/TokenLocation.h"
#include "data/location/TokenLocationFile.h"
#include "data/location/TokenLocationLine.h"
#include "utility/logging/logging.h"
TokenLocationCollection::TokenLocationCollection()
{
}
TokenLocationCollection::~TokenLocationCollection()
{
}
const TokenLocationCollection::TokenLocationFileMapType& TokenLocationCollection::getTokenLocationFiles() const
{
return m_files;
}
size_t TokenLocationCollection::getTokenLocationFileCount() const
{
return m_files.size();
}
const std::map<Id, TokenLocation*>& TokenLocationCollection::getTokenLocations() const
{
return m_locations;
}
size_t TokenLocationCollection::getTokenLocationCount() const
{
return m_locations.size();
}
TokenLocation* TokenLocationCollection::addTokenLocation(
Id tokenId, const std::string& filePath,
unsigned int startLineNumber, unsigned int startColumnNumber,
unsigned int endLineNumber, unsigned int endColumnNumber)
{
if (startLineNumber > endLineNumber || (startLineNumber == endLineNumber && startColumnNumber > endColumnNumber))
{
LOG_ERROR("Can't create TokenLocation with wrong boundaries.");
return nullptr;
}
TokenLocationFile* file = createTokenLocationFile(filePath);
TokenLocation* location =
file->addTokenLocation(tokenId, startLineNumber, startColumnNumber, endLineNumber, endColumnNumber);
m_locations.emplace(location->getId(), location);
return location;
}
void TokenLocationCollection::removeTokenLocation(TokenLocation* location)
{
if (!findTokenLocationById(location->getId()))
{
LOG_ERROR("TokenLocation is not part of this TokenLocationCollection.");
return;
}
m_locations.erase(location->getId());
TokenLocationFile* file = location->getTokenLocationFile();
file->removeTokenLocation(location);
if (!file->getTokenLocationLineCount())
{
m_files.erase(file->getFilePath());
}
}
TokenLocation* TokenLocationCollection::findTokenLocationById(Id id) const
{
std::map<Id, TokenLocation*>::const_iterator it = m_locations.find(id);
if (it != m_locations.end())
{
return it->second;
}
return nullptr;
}
TokenLocationFile* TokenLocationCollection::findTokenLocationFileByPath(const std::string& filePath) const
{
std::map<std::string, std::shared_ptr<TokenLocationFile> >::const_iterator it = m_files.find(filePath);
if (it != m_files.end())
{
return it->second.get();
}
return nullptr;
}
void TokenLocationCollection::forEachTokenLocationFile(std::function<void(TokenLocationFile*)> func) const
{
for (const TokenLocationFilePairType& file : m_files)
{
func(file.second.get());
}
}
TokenLocation* TokenLocationCollection::addTokenLocationAsPlainCopy(const TokenLocation* location)
{
const std::string& filePath = location->getTokenLocationLine()->getTokenLocationFile()->getFilePath();
TokenLocationFile* file = createTokenLocationFile(filePath);
TokenLocation* copy = file->addTokenLocationAsPlainCopy(location);
m_locations.emplace(copy->getId(), copy);
return copy;
}
TokenLocationFile* TokenLocationCollection::createTokenLocationFile(const std::string& filePath)
{
TokenLocationFile* file = findTokenLocationFileByPath(filePath);
if (file)
{
return file;
}
std::shared_ptr<TokenLocationFile> filePtr = std::make_shared<TokenLocationFile>(filePath);
m_files.emplace(filePath, filePtr);
return filePtr.get();
}
std::ostream& operator<<(std::ostream& ostream, const TokenLocationCollection& base)
{
ostream << "Locations:\n";
base.forEachTokenLocationFile([&ostream](TokenLocationFile* f)
{
ostream << *f;
});
return ostream;
}
@@ -0,0 +1,51 @@
#ifndef TOKEN_LOCATION_COLLECTION_H
#define TOKEN_LOCATION_COLLECTION_H
#include <map>
#include <memory>
#include <ostream>
#include <string>
#include "utility/types.h"
class TokenLocation;
class TokenLocationFile;
class TokenLocationCollection
{
public:
typedef std::map<std::string, std::shared_ptr<TokenLocationFile> > TokenLocationFileMapType;
typedef std::pair<std::string, std::shared_ptr<TokenLocationFile> > TokenLocationFilePairType;
TokenLocationCollection();
~TokenLocationCollection();
const TokenLocationFileMapType& getTokenLocationFiles() const;
size_t getTokenLocationFileCount() const;
const std::map<Id, TokenLocation*>& getTokenLocations() const;
size_t getTokenLocationCount() const;
TokenLocation* addTokenLocation(
Id tokenId, const std::string& filePath,
unsigned int startLineNumber, unsigned int startColumnNumber,
unsigned int endLineNumber, unsigned int endColumnNumber);
void removeTokenLocation(TokenLocation* location);
TokenLocation* findTokenLocationById(Id id) const;
TokenLocationFile* findTokenLocationFileByPath(const std::string& filePath) const;
void forEachTokenLocationFile(std::function<void(TokenLocationFile*)> func) const;
TokenLocation* addTokenLocationAsPlainCopy(const TokenLocation* location);
private:
TokenLocationFile* createTokenLocationFile(const std::string& filePath);
TokenLocationFileMapType m_files;
std::map<Id, TokenLocation*> m_locations;
};
std::ostream& operator<<(std::ostream& ostream, const TokenLocationCollection& base);
#endif // TOKEN_LOCATION_COLLECTION_H
+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;
}
+48
View File
@@ -0,0 +1,48 @@
#ifndef TOKEN_LOCATION_FILE_H
#define TOKEN_LOCATION_FILE_H
#include <map>
#include <memory>
#include <ostream>
#include <string>
#include "utility/types.h"
class TokenLocation;
class TokenLocationLine;
class TokenLocationFile
{
public:
typedef std::map<unsigned int, std::shared_ptr<TokenLocationLine> > TokenLocationLineMapType;
typedef std::pair<unsigned int, std::shared_ptr<TokenLocationLine> > TokenLocationLinePairType;
TokenLocationFile(const std::string& filePath);
~TokenLocationFile();
const TokenLocationLineMapType& getTokenLocationLines() const;
size_t getTokenLocationLineCount() const;
const std::string& getFilePath() const;
TokenLocation* addTokenLocation(
Id tokenId,
unsigned int startLineNumber, unsigned int startColumnNumber,
unsigned int endLineNumber, unsigned int endColumnNumber);
void removeTokenLocation(TokenLocation* location);
void forEachTokenLocationLine(std::function<void(TokenLocationLine*)> func) const;
TokenLocation* addTokenLocationAsPlainCopy(const TokenLocation* location);
private:
TokenLocationLine* findTokenLocationLine(unsigned int lineNumber) const;
TokenLocationLine* createTokenLocationLine(unsigned int lineNumber);
std::map<unsigned int, std::shared_ptr<TokenLocationLine> > m_lines;
const std::string m_filePath;
};
std::ostream& operator<<(std::ostream& ostream, const TokenLocationFile& file);
#endif // TOKEN_LOCATION_FILE_H
+113
View File
@@ -0,0 +1,113 @@
#include "data/location/TokenLocationLine.h"
#include "data/location/TokenLocation.h"
#include "data/location/TokenLocationFile.h"
#include "utility/logging/logging.h"
TokenLocationLine::TokenLocationLine(TokenLocationFile* file, unsigned int lineNumber)
: m_file(file)
, m_lineNumber(lineNumber)
{
}
TokenLocationLine::~TokenLocationLine()
{
}
const TokenLocationLine::TokenLocationMapType& TokenLocationLine::getTokenLocations() const
{
return m_locations;
}
size_t TokenLocationLine::getTokenLocationCount() const
{
return m_locations.size();
}
TokenLocationFile* TokenLocationLine::getTokenLocationFile() const
{
return m_file;
}
const std::string& TokenLocationLine::getFilePath() const
{
return m_file->getFilePath();
}
unsigned int TokenLocationLine::getLineNumber() const
{
return m_lineNumber;
}
TokenLocation* TokenLocationLine::addStartTokenLocation(Id tokenId, unsigned int columnNumber)
{
std::shared_ptr<TokenLocation> locationPtr = std::make_shared<TokenLocation>(tokenId, this, columnNumber, true);
m_locations.emplace(columnNumber, locationPtr);
return locationPtr.get();
}
TokenLocation* TokenLocationLine::addEndTokenLocation(TokenLocation* start, unsigned int columnNumber)
{
std::shared_ptr<TokenLocation> locationPtr = std::make_shared<TokenLocation>(
start->getId(), start->getTokenId(), this, columnNumber, false);
start->setOtherTokenLocation(locationPtr.get());
locationPtr->setOtherTokenLocation(start);
m_locations.emplace(columnNumber, locationPtr);
return locationPtr.get();
}
void TokenLocationLine::removeTokenLocation(TokenLocation* location)
{
TokenLocationMapType::iterator it = m_locations.find(location->getColumnNumber());
while (it->first == location->getColumnNumber())
{
if (it->second.get() == location)
{
m_locations.erase(it);
return;
}
it++;
}
LOG_ERROR("TokenLocation can't be removed, it's not part of the TokenLocationLine.");
}
TokenLocation* TokenLocationLine::getTokenLocationById(Id id) const
{
for (const TokenLocationPairType& p : m_locations)
{
if (p.second->getId() == id)
{
return p.second.get();
}
}
return nullptr;
}
void TokenLocationLine::forEachTokenLocation(std::function<void(TokenLocation*)> func) const
{
for (const TokenLocationPairType& location : m_locations)
{
func(location.second.get());
}
}
TokenLocation* TokenLocationLine::addTokenLocationAsPlainCopy(const TokenLocation* location)
{
std::shared_ptr<TokenLocation> locationPtr = location->createPlainCopy(this);
m_locations.emplace(location->getColumnNumber(), locationPtr);
return locationPtr.get();
}
std::ostream& operator<<(std::ostream& ostream, const TokenLocationLine& line)
{
ostream << line.getLineNumber() << ": ";
line.forEachTokenLocation([&ostream](TokenLocation* l)
{
ostream << *l;
});
return ostream;
}
+50
View File
@@ -0,0 +1,50 @@
#ifndef TOKEN_LOCATION_LINE_H
#define TOKEN_LOCATION_LINE_H
#include <map>
#include <memory>
#include <ostream>
#include <string>
#include "utility/types.h"
class TokenLocation;
class TokenLocationFile;
class TokenLocationLine
{
public:
typedef std::multimap<unsigned int, std::shared_ptr<TokenLocation> > TokenLocationMapType;
typedef std::pair<unsigned int, std::shared_ptr<TokenLocation> > TokenLocationPairType;
TokenLocationLine(TokenLocationFile* file, unsigned int lineNumber);
~TokenLocationLine();
const TokenLocationMapType& getTokenLocations() const;
size_t getTokenLocationCount() const;
TokenLocationFile* getTokenLocationFile() const;
const std::string& getFilePath() const;
unsigned int getLineNumber() const;
TokenLocation* addStartTokenLocation(Id tokenId, unsigned int columnNumber);
TokenLocation* addEndTokenLocation(TokenLocation* start, unsigned int columnNumber);
void removeTokenLocation(TokenLocation* location);
TokenLocation* getTokenLocationById(Id id) const;
void forEachTokenLocation(std::function<void(TokenLocation*)> func) const;
TokenLocation* addTokenLocationAsPlainCopy(const TokenLocation* location);
private:
TokenLocationMapType m_locations;
TokenLocationFile* const m_file;
const unsigned int m_lineNumber;
};
std::ostream& operator<<(std::ostream& ostream, const TokenLocationLine& line);
#endif // TOKEN_LOCATION_LINE_H