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
+9 -6
View File
@@ -53,6 +53,15 @@ add_files(
data/graph/Token.cpp
data/graph/Token.h
data/location/TokenLocation.cpp
data/location/TokenLocation.h
data/location/TokenLocationCollection.cpp
data/location/TokenLocationCollection.h
data/location/TokenLocationFile.cpp
data/location/TokenLocationFile.h
data/location/TokenLocationLine.cpp
data/location/TokenLocationLine.h
data/parser/ParseLocation.cpp
data/parser/ParseLocation.h
data/parser/Parser.cpp
@@ -68,12 +77,6 @@ add_files(
data/SearchIndex.h
data/Storage.cpp
data/Storage.h
data/TextLocation.cpp
data/TextLocation.h
data/TextLocationFile.cpp
data/TextLocationFile.h
data/TextLocationLine.cpp
data/TextLocationLine.h
gui/GuiArea.cpp
gui/GuiArea.h
+2
View File
@@ -46,6 +46,8 @@ void Project::parseCode()
parser.parseFiles(
FileSystem::getSourceFilesFromDirectory(ProjectSettings::getInstance()->getSourcePath(), extension)
);
m_storage->logGraph();
m_storage->logLocations();
}
}
+45 -4
View File
@@ -2,6 +2,7 @@
#include <sstream>
#include "data/location/TokenLocation.h"
#include "data/parser/ParseLocation.h"
#include "data/parser/ParseVariable.h"
#include "utility/logging/logging.h"
@@ -29,6 +30,8 @@ void Storage::onClassParsed(const ParseLocation& location, const std::string& fu
Node* node = m_graph.createNodeHierarchy(fullName);
node->setType(Node::NODE_CLASS);
node->setAccess(convertAccessType(access));
addTokenLocation(node, location);
}
void Storage::onStructParsed(const ParseLocation& location, const std::string& fullName, AccessType access)
@@ -38,6 +41,8 @@ void Storage::onStructParsed(const ParseLocation& location, const std::string& f
Node* node = m_graph.createNodeHierarchy(fullName);
node->setType(Node::NODE_STRUCT);
node->setAccess(convertAccessType(access));
addTokenLocation(node, location);
}
void Storage::onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable)
@@ -50,6 +55,8 @@ void Storage::onGlobalVariableParsed(const ParseLocation& location, const ParseV
node->setStatic(variable.isStatic);
m_graph.createEdge(Edge::EDGE_TYPE_OF, node, m_graph.createNodeHierarchy(variable.typeName));
addTokenLocation(node, location);
}
void Storage::onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access)
@@ -69,6 +76,8 @@ void Storage::onFieldParsed(const ParseLocation& location, const ParseVariable&
node->setAccess(convertAccessType(access));
m_graph.createEdge(Edge::EDGE_TYPE_OF, node, m_graph.createNodeHierarchy(variable.typeName));
addTokenLocation(node, location);
}
void Storage::onFunctionParsed(
@@ -86,6 +95,8 @@ void Storage::onFunctionParsed(
{
m_graph.createEdge(Edge::EDGE_PARAMETER_OF, node, m_graph.createNodeHierarchy(var.typeName));
}
addTokenLocation(node, location);
}
void Storage::onMethodParsed(
@@ -113,6 +124,8 @@ void Storage::onMethodParsed(
{
m_graph.createEdge(Edge::EDGE_PARAMETER_OF, node, m_graph.createNodeHierarchy(parameter.typeName));
}
addTokenLocation(node, location);
}
void Storage::onNamespaceParsed(const ParseLocation& location, const std::string& fullName)
@@ -121,6 +134,8 @@ void Storage::onNamespaceParsed(const ParseLocation& location, const std::string
Node* node = m_graph.createNodeHierarchy(fullName);
node->setType(Node::NODE_NAMESPACE);
addTokenLocation(node, location);
}
void Storage::onEnumParsed(const ParseLocation& location, const std::string& fullName, AccessType access)
@@ -130,6 +145,8 @@ void Storage::onEnumParsed(const ParseLocation& location, const std::string& ful
Node* node = m_graph.createNodeHierarchy(fullName);
node->setType(Node::NODE_ENUM);
node->setAccess(convertAccessType(access));
addTokenLocation(node, location);
}
void Storage::onEnumFieldParsed(const ParseLocation& location, const std::string& fullName)
@@ -138,6 +155,8 @@ void Storage::onEnumFieldParsed(const ParseLocation& location, const std::string
Node* node = m_graph.createNodeHierarchy(fullName);
node->setType(Node::NODE_FIELD);
addTokenLocation(node, location);
}
void Storage::logGraph() const
@@ -147,11 +166,11 @@ void Storage::logGraph() const
LOG_INFO(str.str());
}
void Storage::log(std::string type, std::string str, const ParseLocation& location) const
void Storage::logLocations() const
{
std::stringstream info;
info << type << ": " << str << " <" << location.file << " " << location.line << ":" << location.column << ">";
LOG_INFO(info.str());
std::stringstream str;
str << "\n" << m_locationCollection;
LOG_INFO(str.str());
}
Edge::AccessType Storage::convertAccessType(ParserClient::AccessType access) const
@@ -168,3 +187,25 @@ Edge::AccessType Storage::convertAccessType(ParserClient::AccessType access) con
return Edge::ACCESS_NONE;
}
}
TokenLocation* Storage::addTokenLocation(Token* token, const ParseLocation& loc)
{
TokenLocation* location = m_locationCollection.addTokenLocation(
token->getId(), loc.filePath,
loc.startLineNumber, loc.startColumnNumber,
loc.endLineNumber, loc.endColumnNumber
);
token->addLocationId(location->getId());
return location;
}
void Storage::log(std::string type, std::string str, const ParseLocation& location) const
{
std::stringstream info;
info << type << ": " << str;
info << " <" << location.filePath << " ";
info << location.startLineNumber << ":" << location.startColumnNumber << " ";
info << location.endLineNumber << ":" << location.endColumnNumber << ">";
LOG_INFO(info.str());
}
+6 -4
View File
@@ -5,8 +5,8 @@
#include <vector>
#include "data/graph/Graph.h"
#include "data/location/TokenLocationCollection.h"
#include "data/parser/ParserClient.h"
#include "data/TextLocationFile.h"
class Storage: public ParserClient
{
@@ -38,14 +38,16 @@ public:
virtual void onEnumFieldParsed(const ParseLocation& location, const std::string& fullName);
void logGraph() const;
void logLocations() const;
private:
void log(std::string type, std::string str, const ParseLocation& location) const;
Edge::AccessType convertAccessType(ParserClient::AccessType access) const;
TokenLocation* addTokenLocation(Token* token, const ParseLocation& location);
void log(std::string type, std::string str, const ParseLocation& location) const;
Graph m_graph;
std::vector<std::shared_ptr<TextLocationFile> > m_textLocationFiles;
TokenLocationCollection m_locationCollection;
};
#endif // STORAGE_H
-24
View File
@@ -1,24 +0,0 @@
#include "data/TextLocation.h"
#include "data/graph/Token.h"
#include "data/TextLocationLine.h"
TextLocation::TextLocation(
std::weak_ptr<TextLocationLine> textLocationLine,
std::weak_ptr<Token> token,
unsigned int column
)
: m_token(token)
, m_textLocationLine(textLocationLine)
, m_column(column)
{
}
TextLocation::~TextLocation()
{
}
unsigned int TextLocation::getColumn() const
{
return m_column;
}
-28
View File
@@ -1,28 +0,0 @@
#ifndef TEXT_LOCATION_H
#define TEXT_LOCATION_H
#include <memory>
class Token;
class TextLocationLine;
class TextLocation
{
public:
TextLocation(
std::weak_ptr<TextLocationLine> textLocationLine,
std::weak_ptr<Token> token,
unsigned int column
);
~TextLocation();
unsigned int getColumn() const;
private:
const std::weak_ptr<Token> m_token;
const std::weak_ptr<TextLocationLine> m_textLocationLine;
const unsigned int m_column;
};
#endif // TEXT_LOCATION_H
-10
View File
@@ -1,10 +0,0 @@
#include "data/TextLocationFile.h"
TextLocationFile::TextLocationFile(const std::string& filePath)
: m_filePath(filePath)
{
}
TextLocationFile::~TextLocationFile()
{
}
-22
View File
@@ -1,22 +0,0 @@
#ifndef TEXT_LOCATION_FILE_H
#define TEXT_LOCATION_FILE_H
#include <memory>
#include <string>
#include <vector>
#include "data/TextLocationLine.h"
class TextLocationFile
{
public:
TextLocationFile(const std::string& filePath);
~TextLocationFile();
private:
const std::string m_filePath;
std::vector<std::shared_ptr<TextLocationLine> > m_textLocationLine;
};
#endif // TEXT_LOCATION_FILE_H
-18
View File
@@ -1,18 +0,0 @@
#include "data/TextLocationLine.h"
#include "data/TextLocationFile.h"
TextLocationLine::TextLocationLine(std::weak_ptr<TextLocationFile> textLocationFile, unsigned int lineNumber)
: m_textLocationFile(textLocationFile)
, m_lineNumber(lineNumber)
{
}
TextLocationLine::~TextLocationLine()
{
}
unsigned int TextLocationLine::getLineNumber() const
{
return m_lineNumber;
}
-28
View File
@@ -1,28 +0,0 @@
#ifndef TEXT_LOCATION_LINE_H
#define TEXT_LOCATION_LINE_H
#include <memory>
#include <vector>
#include "data/TextLocation.h"
class TextLocationFile;
class TextLocationLine
{
public:
TextLocationLine(std::weak_ptr<TextLocationFile> textLocationFile, unsigned int lineNumber);
~TextLocationLine();
unsigned int getLineNumber() const;
private:
const std::weak_ptr<TextLocationFile> m_textLocationFile;
const unsigned int m_lineNumber;
const std::vector<std::shared_ptr<TextLocation> > m_textLocations;
};
#endif // TEXT_LOCATION_LINE_H
+28 -1
View File
@@ -1,5 +1,8 @@
#include "data/graph/Token.h"
#include "data/location/TokenLocation.h"
#include "utility/logging/logging.h"
Token::Token()
: m_id(s_nextId++)
{
@@ -14,9 +17,33 @@ Id Token::getId() const
return m_id;
}
Id Token::s_nextId = 1;
const std::vector<Id>& Token::getLocationIds() const
{
return m_locationIds;
}
void Token::addLocationId(Id locationId)
{
m_locationIds.push_back(locationId);
}
void Token::removeLocationId(Id locationId)
{
for (std::vector<Id>::const_iterator it = m_locationIds.begin(); it != m_locationIds.end(); it++)
{
if (*it == locationId)
{
m_locationIds.erase(it);
return;
}
}
LOG_ERROR("Location Id was not referenced by this Token.");
}
Token::Token(Id id)
: m_id(id)
{
}
Id Token::s_nextId = 1;
+9
View File
@@ -1,6 +1,8 @@
#ifndef TOKEN_H
#define TOKEN_H
#include <vector>
#include "utility/types.h"
class Token
@@ -14,6 +16,11 @@ public:
virtual bool isNode() const = 0;
virtual bool isEdge() const = 0;
const std::vector<Id>& getLocationIds() const;
void addLocationId(Id locationId);
void removeLocationId(Id locationId);
protected:
// Constructor for plain copies of Node and Edge
Token(Id id);
@@ -25,6 +32,8 @@ private:
void operator=(const Token&);
const Id m_id;
std::vector<Id> m_locationIds;
};
#endif // TOKEN_H
+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
+10 -4
View File
@@ -1,8 +1,14 @@
#include "data/parser/ParseLocation.h"
ParseLocation::ParseLocation(const std::string& file, unsigned int line, unsigned int column)
: file(file)
, line(line)
, column(column)
ParseLocation::ParseLocation(
const std::string& filePath,
unsigned int startLineNumber, unsigned int startColumnNumber,
unsigned int endLineNumber, unsigned int endColumnNumber
)
: filePath(filePath)
, startLineNumber(startLineNumber)
, startColumnNumber(startColumnNumber)
, endLineNumber(endLineNumber)
, endColumnNumber(endColumnNumber)
{
}
+9 -4
View File
@@ -5,11 +5,16 @@
struct ParseLocation
{
ParseLocation(const std::string& file, unsigned int line, unsigned int column);
ParseLocation(
const std::string& filePath,
unsigned int startLineNumber, unsigned int startColumnNumber,
unsigned int endLineNumber, unsigned int endColumnNumber);
const std::string file;
const unsigned int line;
const unsigned int column;
const std::string filePath;
unsigned int startLineNumber;
unsigned int startColumnNumber;
unsigned int endLineNumber;
unsigned int endColumnNumber;
};
#endif // PARSE_LOCATION_H
+34 -44
View File
@@ -15,12 +15,10 @@ ASTVisitor::~ASTVisitor()
bool ASTVisitor::VisitTypedefDecl(const clang::TypedefDecl* declaration)
{
const clang::SourceLocation& location = declaration->getLocStart();
if (isValidLocation(location))
if (hasValidLocation(declaration))
{
m_client->onTypedefParsed(
getParseLocation(location),
getParseLocation(declaration),
declaration->getQualifiedNameAsString(),
declaration->getUnderlyingType().getAsString(),
convertAccessType(declaration->getAccess())
@@ -32,14 +30,12 @@ bool ASTVisitor::VisitTypedefDecl(const clang::TypedefDecl* declaration)
bool ASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* declaration)
{
const clang::SourceLocation& location = declaration->getLocStart();
if (isValidLocation(location))
if (hasValidLocation(declaration))
{
if (declaration->isClass())
{
m_client->onClassParsed(
getParseLocation(location),
getParseLocation(declaration),
declaration->getQualifiedNameAsString(),
convertAccessType(declaration->getAccess())
);
@@ -47,7 +43,7 @@ bool ASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* declaration)
else if (declaration->isStruct())
{
m_client->onStructParsed(
getParseLocation(location),
getParseLocation(declaration),
declaration->getQualifiedNameAsString(),
convertAccessType(declaration->getAccess())
);
@@ -65,20 +61,18 @@ bool ASTVisitor::VisitVarDecl(clang::VarDecl* declaration)
return true;
}
const clang::SourceLocation& location = declaration->getLocStart();
if (isValidLocation(location))
if (hasValidLocation(declaration))
{
clang::AccessSpecifier access = declaration->getAccess();
if (access == clang::AS_none)
{
m_client->onGlobalVariableParsed(getParseLocation(location), getParseVariable(declaration));
m_client->onGlobalVariableParsed(getParseLocation(declaration), getParseVariable(declaration));
}
else
{
m_client->onFieldParsed(
getParseLocation(location),
getParseLocation(declaration),
getParseVariable(declaration),
convertAccessType(declaration->getAccess())
);
@@ -90,12 +84,10 @@ bool ASTVisitor::VisitVarDecl(clang::VarDecl* declaration)
bool ASTVisitor::VisitFieldDecl(clang::FieldDecl* declaration)
{
const clang::SourceLocation& location = declaration->getLocStart();
if (isValidLocation(location))
if (hasValidLocation(declaration))
{
m_client->onFieldParsed(
getParseLocation(location),
getParseLocation(declaration),
getParseVariable(declaration),
convertAccessType(declaration->getAccess())
);
@@ -112,12 +104,10 @@ bool ASTVisitor::VisitFunctionDecl(clang::FunctionDecl* declaration)
return true;
}
const clang::SourceLocation& location = declaration->getLocStart();
if (isValidLocation(location))
if (hasValidLocation(declaration))
{
m_client->onFunctionParsed(
getParseLocation(location),
getParseLocation(declaration),
declaration->getQualifiedNameAsString(),
getTypeName(declaration->getReturnType()),
getParameters(declaration)
@@ -129,9 +119,7 @@ bool ASTVisitor::VisitFunctionDecl(clang::FunctionDecl* declaration)
bool ASTVisitor::VisitCXXMethodDecl(clang::CXXMethodDecl* declaration)
{
const clang::SourceLocation& location = declaration->getLocStart();
if (isValidLocation(location))
if (hasValidLocation(declaration))
{
ParserClient::AbstractionType abstraction = ParserClient::ABSTRACTION_NONE;
if (declaration->isPure())
@@ -144,7 +132,7 @@ bool ASTVisitor::VisitCXXMethodDecl(clang::CXXMethodDecl* declaration)
}
m_client->onMethodParsed(
getParseLocation(location),
getParseLocation(declaration),
declaration->getQualifiedNameAsString(),
getTypeName(declaration->getReturnType()),
getParameters(declaration),
@@ -160,11 +148,9 @@ bool ASTVisitor::VisitCXXMethodDecl(clang::CXXMethodDecl* declaration)
bool ASTVisitor::VisitNamespaceDecl(clang::NamespaceDecl* declaration)
{
const clang::SourceLocation& location = declaration->getLocStart();
if (isValidLocation(location))
if (hasValidLocation(declaration))
{
m_client->onNamespaceParsed(getParseLocation(location), declaration->getQualifiedNameAsString());
m_client->onNamespaceParsed(getParseLocation(declaration), declaration->getQualifiedNameAsString());
}
return true;
@@ -172,12 +158,10 @@ bool ASTVisitor::VisitNamespaceDecl(clang::NamespaceDecl* declaration)
bool ASTVisitor::VisitEnumDecl(clang::EnumDecl* declaration)
{
const clang::SourceLocation& location = declaration->getLocStart();
if (isValidLocation(location))
if (hasValidLocation(declaration))
{
m_client->onEnumParsed(
getParseLocation(location),
getParseLocation(declaration),
declaration->getQualifiedNameAsString(),
convertAccessType(declaration->getAccess())
);
@@ -188,28 +172,34 @@ bool ASTVisitor::VisitEnumDecl(clang::EnumDecl* declaration)
bool ASTVisitor::VisitEnumConstantDecl(clang::EnumConstantDecl* declaration)
{
const clang::SourceLocation& location = declaration->getLocStart();
if (isValidLocation(location))
if (hasValidLocation(declaration))
{
m_client->onEnumFieldParsed(getParseLocation(location), declaration->getQualifiedNameAsString());
m_client->onEnumFieldParsed(getParseLocation(declaration), declaration->getQualifiedNameAsString());
}
return true;
}
bool ASTVisitor::isValidLocation(const clang::SourceLocation& location) const
bool ASTVisitor::hasValidLocation(const clang::Decl* declaration) const
{
const clang::SourceLocation& location = declaration->getLocStart();
return location.isValid() && m_context->getSourceManager().isWrittenInMainFile(location);
}
ParseLocation ASTVisitor::getParseLocation(const clang::SourceLocation& location) const
ParseLocation ASTVisitor::getParseLocation(const clang::Decl* declaration) const
{
clang::FullSourceLoc fullLocation = m_context->getFullLoc(location);
const clang::SourceRange& sourceRange = declaration->getSourceRange();
const clang::SourceManager& sourceManager = m_context->getSourceManager();
const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(sourceRange.getBegin());
const clang::PresumedLoc& presumedEnd = sourceManager.getPresumedLoc(sourceRange.getEnd());
return ParseLocation(
m_context->getSourceManager().getFilename(location),
fullLocation.getSpellingLineNumber(),
fullLocation.getSpellingColumnNumber()
presumedBegin.getFilename(),
presumedBegin.getLine(),
presumedBegin.getColumn(),
presumedEnd.getLine(),
presumedEnd.getColumn()
);
}
+2 -2
View File
@@ -33,8 +33,8 @@ public:
virtual bool VisitEnumConstantDecl(clang::EnumConstantDecl* declaration); // enum fields
private:
bool isValidLocation(const clang::SourceLocation& location) const;
ParseLocation getParseLocation(const clang::SourceLocation& location) const;
bool hasValidLocation(const clang::Decl* declaration) const;
ParseLocation getParseLocation(const clang::Decl* declaration) const;
ParseVariable getParseVariable(clang::ValueDecl* declaration) const;
std::vector<ParseVariable> getParameters(clang::FunctionDecl* declaration) const;
std::string getTypeName(const clang::QualType& type) const;
+1
View File
@@ -11,6 +11,7 @@ add_files(
TestSuiteFixture.cpp
TestSuiteFixture.h
TextAccessTestSuite.h
TokenLocationCollectionTestSuite.h
UtilityStringTestSuite.h
Vector2TestSuite.h
)
+57 -44
View File
@@ -1,5 +1,7 @@
#include "cxxtest/TestSuite.h"
#include <sstream>
#include "data/parser/cxx/CxxParser.h"
#include "data/parser/ParseLocation.h"
#include "data/parser/ParserClient.h"
@@ -21,7 +23,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->classes.size(), 1);
TS_ASSERT_EQUALS(client->classes[0], "A");
TS_ASSERT_EQUALS(client->classes[0], "A <1:1 3:1>");
}
void test_cxx_parser_finds_global_class_forward_declaration()
@@ -34,7 +36,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->classes.size(), 1);
TS_ASSERT_EQUALS(client->classes[0], "A");
TS_ASSERT_EQUALS(client->classes[0], "A <1:1 1:7>");
}
void test_cxx_parser_finds_nested_class_definition() // TODO: test different access types here
@@ -51,8 +53,8 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->classes.size(), 2);
TS_ASSERT_EQUALS(client->classes[0], "A");
TS_ASSERT_EQUALS(client->classes[1], "public A::B");
TS_ASSERT_EQUALS(client->classes[0], "A <1:1 5:1>");
TS_ASSERT_EQUALS(client->classes[1], "public A::B <4:2 4:8>");
}
void test_cxx_parser_finds_class_definition_in_namespace()
@@ -68,7 +70,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->classes.size(), 1);
TS_ASSERT_EQUALS(client->classes[0], "a::B");
TS_ASSERT_EQUALS(client->classes[0], "a::B <3:2 3:8>");
}
void test_cxx_parser_finds_global_struct_definition()
@@ -83,7 +85,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->structs.size(), 1);
TS_ASSERT_EQUALS(client->structs[0], "A");
TS_ASSERT_EQUALS(client->structs[0], "A <1:1 3:1>");
}
void test_cxx_parser_finds_global_struct_forward_declaration()
@@ -96,7 +98,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->structs.size(), 1);
TS_ASSERT_EQUALS(client->structs[0], "A");
TS_ASSERT_EQUALS(client->structs[0], "A <1:1 1:8>");
}
void test_cxx_parser_finds_struct_definition_in_class()
@@ -114,7 +116,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->structs.size(), 1);
TS_ASSERT_EQUALS(client->structs[0], "private A::B");
TS_ASSERT_EQUALS(client->structs[0], "private A::B <3:2 5:2>");
}
void test_cxx_parser_finds_struct_definition_in_namespace()
@@ -132,7 +134,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->structs.size(), 1);
TS_ASSERT_EQUALS(client->structs[0], "A::B");
TS_ASSERT_EQUALS(client->structs[0], "A::B <3:2 5:2>");
}
void test_cxx_parser_finds_variable_definitions_in_global_scope()
@@ -147,8 +149,8 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->globals.size(), 2);
TS_ASSERT_EQUALS(client->globals[0], "int x");
TS_ASSERT_EQUALS(client->globals[1], "A * b");
TS_ASSERT_EQUALS(client->globals[0], "int x <1:1 1:5>");
TS_ASSERT_EQUALS(client->globals[1], "A * b <3:1 3:4>");
}
void test_cxx_parser_finds_variable_definitions_in_namespace_scope()
@@ -166,8 +168,8 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->globals.size(), 2);
TS_ASSERT_EQUALS(client->globals[0], "int n::x");
TS_ASSERT_EQUALS(client->globals[1], "n::A * n::b");
TS_ASSERT_EQUALS(client->globals[0], "int n::x <2:2 2:6>");
TS_ASSERT_EQUALS(client->globals[1], "n::A * n::b <4:2 4:5>");
}
void test_cxx_parser_finds_field_in_nested_class()
@@ -188,7 +190,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->fields.size(), 1);
TS_ASSERT_EQUALS(client->fields[0], "private static const int B::C::amount");
TS_ASSERT_EQUALS(client->fields[0], "private static const int B::C::amount <7:3 7:20>");
}
void test_cxx_parser_finds_field_in_global_class()
@@ -199,15 +201,15 @@ public:
"class B\n"
"{\n"
"public:\n"
" B() : count(0) {};"
" B() : count(0) {};\n"
"private:\n"
" const int count;"
" const int count;\n"
"};\n";
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->fields.size(), 1);
TS_ASSERT_EQUALS(client->fields[0], "private const int B::count");
TS_ASSERT_EQUALS(client->fields[0], "private const int B::count <6:2 6:12>");
}
void test_cxx_parser_finds_function_in_global_namespace()
@@ -223,7 +225,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->functions.size(), 1);
TS_ASSERT_EQUALS(client->functions[0], "int ceil(float a)");
TS_ASSERT_EQUALS(client->functions[0], "int ceil(float a) <1:1 4:1>");
}
void test_cxx_parser_finds_function_in_anonymous_namespace()
@@ -239,7 +241,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->functions.size(), 1);
TS_ASSERT_EQUALS(client->functions[0], "int (anonymous namespace)::sum(int a, int b)");
TS_ASSERT_EQUALS(client->functions[0], "int (anonymous namespace)::sum(int a, int b) <3:2 3:22>");
}
void test_cxx_parser_finds_method_declaration()
@@ -256,7 +258,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->methods.size(), 1);
TS_ASSERT_EQUALS(client->methods[0], "public void B::B()");
TS_ASSERT_EQUALS(client->methods[0], "public void B::B() <4:2 4:4>");
}
void test_cxx_parser_finds_method_declaration_and_definition()
@@ -276,8 +278,8 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->methods.size(), 2);
TS_ASSERT_EQUALS(client->methods[0], "public void B::B()");
TS_ASSERT_EQUALS(client->methods[1], "public void B::B()");
TS_ASSERT_EQUALS(client->methods[0], "public void B::B() <4:2 4:4>");
TS_ASSERT_EQUALS(client->methods[1], "public void B::B() <6:1 8:1>");
}
void test_cxx_parser_finds_pure_virtual_method()
@@ -294,7 +296,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->methods.size(), 1);
TS_ASSERT_EQUALS(client->methods[0], "protected pure virtual void B::process()");
TS_ASSERT_EQUALS(client->methods[0], "protected pure virtual void B::process() <4:2 4:27>");
}
void test_cxx_parser_finds_method_declared_in_nested_class()
@@ -313,7 +315,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->methods.size(), 1);
TS_ASSERT_EQUALS(client->methods[0], "private _Bool B::C::isGreat() const");
TS_ASSERT_EQUALS(client->methods[0], "private _Bool B::C::isGreat() const <5:3 5:18>");
}
void test_cxx_parser_finds_named_namespace()
@@ -322,13 +324,13 @@ public:
CxxParser parser(client);
std::string text =
"namespace A\n"
"{"
"{\n"
"}\n";
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->namespaces.size(), 1);
TS_ASSERT_EQUALS(client->namespaces[0], "A");
TS_ASSERT_EQUALS(client->namespaces[0], "A <1:1 3:1>");
}
void test_cxx_parser_finds_anonymous_namespace()
@@ -343,7 +345,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->namespaces.size(), 1);
TS_ASSERT_EQUALS(client->namespaces[0], "(anonymous)");
TS_ASSERT_EQUALS(client->namespaces[0], "(anonymous) <1:1 3:1>");
}
void test_cxx_parser_finds_enum_defined_in_global_namespace()
@@ -358,7 +360,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->enums.size(), 1);
TS_ASSERT_EQUALS(client->enums[0], "E");
TS_ASSERT_EQUALS(client->enums[0], "E <1:1 3:1>");
}
void test_cxx_parser_finds_enum_defined_in_class()
@@ -377,7 +379,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->enums.size(), 1);
TS_ASSERT_EQUALS(client->enums[0], "public B::Z");
TS_ASSERT_EQUALS(client->enums[0], "public B::Z <4:2 6:2>");
}
void test_cxx_parser_finds_enum_defined_in_namespace()
@@ -395,7 +397,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->enums.size(), 1);
TS_ASSERT_EQUALS(client->enums[0], "n::Z");
TS_ASSERT_EQUALS(client->enums[0], "n::Z <3:2 5:2>");
}
void test_cxx_parser_finds_enum_field_in_global_enum()
@@ -411,7 +413,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->enumFields.size(), 1);
TS_ASSERT_EQUALS(client->enumFields[0], "E::P");
TS_ASSERT_EQUALS(client->enumFields[0], "E::P <3:2 3:2>");
}
void test_cxx_parser_finds_typedef_in_global_namespace()
@@ -423,7 +425,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->typedefs.size(), 1);
TS_ASSERT_EQUALS(client->typedefs[0], "unsigned int -> uint");
TS_ASSERT_EQUALS(client->typedefs[0], "unsigned int -> uint <1:1 1:22>");
}
void test_cxx_parser_finds_typedef_in_named_namespace()
@@ -439,7 +441,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->typedefs.size(), 1);
TS_ASSERT_EQUALS(client->typedefs[0], "unsigned int -> test::uint");
TS_ASSERT_EQUALS(client->typedefs[0], "unsigned int -> test::uint <3:2 3:23>");
}
void test_cxx_parser_finds_typedef_in_anonymous_namespace()
@@ -455,7 +457,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->typedefs.size(), 1);
TS_ASSERT_EQUALS(client->typedefs[0], "unsigned int -> (anonymous namespace)::uint");
TS_ASSERT_EQUALS(client->typedefs[0], "unsigned int -> (anonymous namespace)::uint <3:2 3:23>");
}
void test_cxx_parser_finds_typedef_that_uses_type_defined_in_named_namespace()
@@ -472,7 +474,7 @@ public:
parser.parseFile(TextAccess::createFromString(text));
TS_ASSERT_EQUALS(client->typedefs.size(), 1);
TS_ASSERT_EQUALS(client->typedefs[0], "test::TestStruct -> globalTestStruct");
TS_ASSERT_EQUALS(client->typedefs[0], "test::TestStruct -> globalTestStruct <5:1 5:26>");
}
void test_cxx_parser_parses_multiple_files()
@@ -506,27 +508,28 @@ private:
AccessType access
)
{
typedefs.push_back(addAccessPrefix(underlyingFullName + " -> " + fullName, access));
std::string str = addAccessPrefix(underlyingFullName + " -> " + fullName, access);
typedefs.push_back(addLocationSuffix(str, location));
}
virtual void onClassParsed(const ParseLocation& location, const std::string& fullName, AccessType access)
{
classes.push_back(addAccessPrefix(fullName, access));
classes.push_back(addLocationSuffix(addAccessPrefix(fullName, access), location));
}
virtual void onStructParsed(const ParseLocation& location, const std::string& fullName, AccessType access)
{
structs.push_back(addAccessPrefix(fullName, access));
structs.push_back(addLocationSuffix(addAccessPrefix(fullName, access), location));
}
virtual void onGlobalVariableParsed(const ParseLocation& location, const ParseVariable& variable)
{
globals.push_back(variableStr(variable));
globals.push_back(addLocationSuffix(variableStr(variable), location));
}
virtual void onFieldParsed(const ParseLocation& location, const ParseVariable& variable, AccessType access)
{
fields.push_back(addAccessPrefix(variableStr(variable), access));
fields.push_back(addLocationSuffix(addAccessPrefix(variableStr(variable), access), location));
}
virtual void onFunctionParsed(
@@ -534,7 +537,8 @@ private:
const std::vector<ParseVariable>& parameters
)
{
functions.push_back(returnTypeName + " " + fullName + parameterStr(parameters));
std::string str = returnTypeName + " " + fullName + parameterStr(parameters);
functions.push_back(addLocationSuffix(str, location));
}
virtual void onMethodParsed(
@@ -546,22 +550,23 @@ private:
std::string str = returnTypeName + " " + fullName + parameterStr(parameters);
str = addStaticPrefix(addAbstractionPrefix(str, abstraction), isStatic);
str = addConstPrefix(addAccessPrefix(str, access), isConst, false);
str = addLocationSuffix(str, location);
methods.push_back(str);
}
virtual void onNamespaceParsed(const ParseLocation& location, const std::string& fullName)
{
namespaces.push_back(fullName);
namespaces.push_back(addLocationSuffix(fullName, location));
}
virtual void onEnumParsed(const ParseLocation& location, const std::string& fullName, AccessType access)
{
enums.push_back(addAccessPrefix(fullName, access));
enums.push_back(addLocationSuffix(addAccessPrefix(fullName, access), location));
}
virtual void onEnumFieldParsed(const ParseLocation& location, const std::string& fullName)
{
enumFields.push_back(fullName);
enumFields.push_back(addLocationSuffix(fullName, location));
}
std::vector<std::string> typedefs;
@@ -641,5 +646,13 @@ private:
}
return str + ")";
}
std::string addLocationSuffix(const std::string& str, const ParseLocation& location)
{
std::stringstream ss;
ss << str << " <" << location.startLineNumber << ":" << location.startColumnNumber << " ";
ss << location.endLineNumber << ":" << location.endColumnNumber << ">";
return ss.str();
}
};
};
+162
View File
@@ -0,0 +1,162 @@
#include "cxxtest/TestSuite.h"
#include "data/location/TokenLocation.h"
#include "data/location/TokenLocationCollection.h"
#include "data/location/TokenLocationFile.h"
#include "data/location/TokenLocationLine.h"
class TokenLocationCollectionTestSuite : public CxxTest::TestSuite
{
public:
void test_token_locations_get_created_with_other_end()
{
TokenLocationCollection collection;
TokenLocation* a = collection.addTokenLocation(1, "file.c", 2, 3, 4, 5);
TS_ASSERT(a);
TS_ASSERT(a->isStartTokenLocation());
TS_ASSERT(!a->isEndTokenLocation());
TokenLocation* b = a->getOtherTokenLocation();
TS_ASSERT(b);
TS_ASSERT(!b->isStartTokenLocation());
TS_ASSERT(b->isEndTokenLocation());
TS_ASSERT_EQUALS(a, b->getOtherTokenLocation());
TS_ASSERT_EQUALS(a, b->getStartTokenLocation());
TS_ASSERT_EQUALS(a, a->getStartTokenLocation());
TS_ASSERT_EQUALS(b, a->getEndTokenLocation());
TS_ASSERT_EQUALS(b, b->getEndTokenLocation());
}
void test_token_locations_do_not_get_created_with_wrong_input()
{
TokenLocationCollection collection;
TokenLocation* a = collection.addTokenLocation(1, "file.c", 2, 3, 2, 1);
TokenLocation* b = collection.addTokenLocation(1, "file.c", 4, 1, 1, 10);
TS_ASSERT(!a);
TS_ASSERT(!b);
}
void test_token_locations_get_unique_id_but_both_ends_have_the_same()
{
TokenLocationCollection collection;
TokenLocation* a = collection.addTokenLocation(1, "file.c", 1, 1, 1, 1);
TokenLocation* b = collection.addTokenLocation(2, "file.c", 1, 1, 1, 1);
TokenLocation* c = collection.addTokenLocation(3, "file.c", 1, 1, 1, 1);
TS_ASSERT_EQUALS(1, collection.getTokenLocationFileCount());
TS_ASSERT_EQUALS(3, collection.getTokenLocationCount());
TS_ASSERT_DIFFERS(a->getId(), b->getId());
TS_ASSERT_DIFFERS(b->getId(), c->getId());
TS_ASSERT_DIFFERS(c->getId(), a->getId());
TS_ASSERT_EQUALS(a->getId(), a->getOtherTokenLocation()->getId());
TS_ASSERT_EQUALS(b->getId(), b->getOtherTokenLocation()->getId());
TS_ASSERT_EQUALS(c->getId(), c->getOtherTokenLocation()->getId());
}
void test_token_locations_have_right_file_path_line_column_and_token_id()
{
TokenLocationCollection collection;
TokenLocation* a = collection.addTokenLocation(1, "file.c", 2, 3, 4, 5);
TS_ASSERT_EQUALS(1, a->getTokenId());
TS_ASSERT_EQUALS(2, a->getLineNumber());
TS_ASSERT_EQUALS(3, a->getColumnNumber());
TS_ASSERT_EQUALS(4, a->getOtherTokenLocation()->getLineNumber());
TS_ASSERT_EQUALS(5, a->getOtherTokenLocation()->getColumnNumber());
TS_ASSERT_EQUALS("file.c", a->getFilePath());
}
void test_finding_token_locations_by_id()
{
TokenLocationCollection collection;
TokenLocation* a = collection.addTokenLocation(1, "file.c", 2, 3, 4, 5);
TokenLocation* b = collection.addTokenLocation(6, "file.c", 7, 8, 9, 10);
TS_ASSERT_EQUALS(a, collection.findTokenLocationById(a->getId()));
TS_ASSERT_EQUALS(b, collection.findTokenLocationById(b->getId()));
}
void test_removing_token_locations()
{
TokenLocationCollection collection;
TokenLocation* a = collection.addTokenLocation(1, "file.c", 2, 3, 4, 5);
TokenLocation* b = collection.addTokenLocation(1, "file.c", 3, 3, 4, 5);
TokenLocation* c = collection.addTokenLocation(1, "file.c", 1, 3, 5, 5);
TokenLocation* d = collection.addTokenLocation(1, "file2.c", 1, 3, 5, 5);
TS_ASSERT_EQUALS(2, collection.getTokenLocationFileCount());
TS_ASSERT_EQUALS(4, collection.getTokenLocationCount());
TS_ASSERT_EQUALS(5, c->getTokenLocationFile()->getTokenLocationLineCount());
Id ida = a->getId();
Id idb = b->getId();
Id idc = c->getId();
collection.removeTokenLocation(a);
collection.removeTokenLocation(b->getOtherTokenLocation());
collection.removeTokenLocation(d);
TS_ASSERT(!collection.findTokenLocationById(ida));
TS_ASSERT(!collection.findTokenLocationById(idb));
TS_ASSERT_EQUALS(c, collection.findTokenLocationById(idc));
TS_ASSERT_EQUALS(1, collection.getTokenLocationFileCount());
TS_ASSERT_EQUALS(1, collection.getTokenLocationCount());
TS_ASSERT_EQUALS(2, c->getTokenLocationFile()->getTokenLocationLineCount());
}
void test_creating_plain_copy_of_all_locations_in_line_range()
{
TokenLocationCollection collection;
TokenLocation* a = collection.addTokenLocation(1, "file.c", 2, 3, 4, 5);
TokenLocation* b = collection.addTokenLocation(1, "file.c", 3, 3, 4, 5);
TokenLocation* c = collection.addTokenLocation(1, "file.c", 1, 3, 5, 5);
TokenLocation* d = collection.addTokenLocation(1, "file.c", 1, 5, 4, 5);
Id ida = a->getId();
Id idb = b->getId();
Id idc = c->getId();
Id idd = d->getId();
unsigned int fromLine = 2;
unsigned int toLine = 4;
TokenLocationCollection copy;
TokenLocation* x = collection.findTokenLocationById(ida);
x->getTokenLocationFile()->forEachTokenLocationLine([&copy, fromLine, toLine](TokenLocationLine* line)
{
unsigned int l = line->getLineNumber();
if (l >= fromLine && l <= toLine)
{
line->forEachTokenLocation([&copy](TokenLocation* location)
{
copy.addTokenLocationAsPlainCopy(location);
});
}
});
TS_ASSERT_EQUALS(1, copy.getTokenLocationFileCount());
TS_ASSERT_EQUALS(3, copy.getTokenLocationCount());
TS_ASSERT(copy.findTokenLocationById(ida));
TS_ASSERT(copy.findTokenLocationById(idb));
TS_ASSERT(!copy.findTokenLocationById(idc));
TS_ASSERT(copy.findTokenLocationById(idd));
TS_ASSERT_DIFFERS(a, copy.findTokenLocationById(ida));
TS_ASSERT_DIFFERS(d, copy.findTokenLocationById(idd));
TS_ASSERT(copy.findTokenLocationById(ida)->getStartTokenLocation());
TS_ASSERT(copy.findTokenLocationById(ida)->getEndTokenLocation());
TS_ASSERT(!copy.findTokenLocationById(idd)->getStartTokenLocation());
TS_ASSERT(copy.findTokenLocationById(idd)->getEndTokenLocation());
}
};