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:
@@ -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
|
||||
|
||||
@@ -46,6 +46,8 @@ void Project::parseCode()
|
||||
parser.parseFiles(
|
||||
FileSystem::getSourceFilesFromDirectory(ProjectSettings::getInstance()->getSourcePath(), extension)
|
||||
);
|
||||
|
||||
m_storage->logGraph();
|
||||
m_storage->logLocations();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,10 +0,0 @@
|
||||
#include "data/TextLocationFile.h"
|
||||
|
||||
TextLocationFile::TextLocationFile(const std::string& filePath)
|
||||
: m_filePath(filePath)
|
||||
{
|
||||
}
|
||||
|
||||
TextLocationFile::~TextLocationFile()
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -11,6 +11,7 @@ add_files(
|
||||
TestSuiteFixture.cpp
|
||||
TestSuiteFixture.h
|
||||
TextAccessTestSuite.h
|
||||
TokenLocationCollectionTestSuite.h
|
||||
UtilityStringTestSuite.h
|
||||
Vector2TestSuite.h
|
||||
)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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([©, fromLine, toLine](TokenLocationLine* line)
|
||||
{
|
||||
unsigned int l = line->getLineNumber();
|
||||
if (l >= fromLine && l <= toLine)
|
||||
{
|
||||
line->forEachTokenLocation([©](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());
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user